文章目錄
logging 的基本知識參照:
Python日誌模塊-logging
Python日誌庫logging總結-可能是目前爲止將logging庫總結的最好的一篇文章
handler 參數設置
1、基本知識總結
1、日誌等級
默認分爲六種日誌級別(括號爲級別對應的數值)
日誌等級(level) | 描述 |
---|---|
NOTSET(0) | |
DEBUG(10) | 最詳細的日誌信息,典型應用場景是 問題診斷 |
INFO(20) | 信息詳細程度僅次於DEBUG,通常只記錄關鍵節點信息,用於確認一切都是按照我們預期的那樣進行工作 |
WARNING(30) | 當某些不期望的事情發生時記錄的信息(如,磁盤可用空間較低),但是此時應用程序還是正常運行的 |
ERROR(40) | 由於一個更嚴重的問題導致某些功能不能正常運行時記錄的信息 |
CRITICAL(50) | 當發生嚴重錯誤,導致應用程序不能繼續運行時記錄的信息 |
我們自定義日誌級別時注意不要和默認的日誌級別數值相同,logging 執行時輸出大於等於設置的日誌級別的日誌信息,如設置日誌級別是 INFO,則 INFO、WARNING、ERROR、CRITICAL 級別的日誌都會輸出。
2、logging模塊定義的模塊級別的常用函數
函數 | 說明 |
---|---|
logging.debug(msg, *args, **kwargs) | 創建一條嚴重級別爲DEBUG的日誌記錄 |
logging.info(msg, *args, **kwargs) | 創建一條嚴重級別爲INFO的日誌記錄 |
logging.warning(msg, *args, **kwargs) | 創建一條嚴重級別爲WARNING的日誌記錄 |
logging.error(msg, *args, **kwargs) | 創建一條嚴重級別爲ERROR的日誌記錄 |
logging.critical(msg, *args, **kwargs) | 創建一條嚴重級別爲CRITICAL的日誌記錄 |
logging.log(level, *args, **kwargs) | 創建一條嚴重級別爲level的日誌記錄 |
logging.basicConfig(**kwargs) | 對root logger進行一次性配置 |
3、logging.basicConfig()函數包含參數說明
參數名稱 | 描述 |
---|---|
filename | 指定日誌輸出目標文件的文件名,可以寫文件名也可以寫文件的完整的絕對路徑,寫文件名日誌放執行文件目錄下,寫完整路徑按照完整路徑生成日誌文件),指定該設置項後日志信心就不會被輸出到控制檯了 |
filemode | 指定日誌文件的打開模式,默認爲’a’。需要注意的是,該選項要在filename指定時纔有效 【r[+]、w[+]、a[+]】 |
format | 指定日誌格式字符串,即指定日誌輸出時所包含的字段信息以及它們的順序。logging模塊定義的格式字段下面會列出。 |
datefmt | 指定日期/時間格式。需要注意的是,該選項要在format中包含時間字段%(asctime)s時纔有效 |
level | 指定日誌器的日誌級別 |
stream | 指定日誌輸出目標stream,如sys.stdout、sys.stderr以及網絡stream。需要說明的是,stream和filename不能同時提供,否則會引發 ValueError異常 |
handles | 定義處理器,用來創建 Handler 對象,不能和 filename 、stream 參數一起使用,否則也會拋出 ValueError 異常 |
4、logging定義好的formmat 格式
字段/屬性名稱 | 使用格式 | 描述 |
---|---|---|
asctime | %(asctime)s | 將日誌的時間構造成可讀的形式,默認情況下是‘2016-02-08 12:00:00,123’精確到毫秒 |
name | %(name)s | 所使用的日誌器名稱,默認是’root’,因爲默認使用的是 rootLogger |
filename | %(filename)s | 調用日誌輸出函數的模塊的文件名; pathname的文件名部分,包含文件後綴 |
funcName | %(funcName)s | 由哪個function發出的log, 調用日誌輸出函數的函數名 |
levelname | %(levelname)s | 日誌的最終等級(被filter修改後的) |
message | %(message)s | 日誌信息, 日誌記錄的文本內容 |
lineno | %(lineno)d | 當前日誌的行號, 調用日誌輸出函數的語句所在的代碼行 |
levelno | %(levelno)s | 該日誌記錄的數字形式的日誌級別(10, 20, 30, 40, 50) |
pathname | %(pathname)s | 完整路徑 ,調用日誌輸出函數的模塊的完整路徑名,可能沒有 |
process | %(process)s | 當前進程, 進程ID。可能沒有 |
processName | %(processName)s | 進程名稱,Python 3.1新增 |
thread | %(thread)s | 當前線程, 線程ID。可能沒有 |
threadName | %(thread)s | 線程名稱 |
module | %(module)s | 調用日誌輸出函數的模塊名, filename的名稱部分,不包含後綴即不包含文件後綴的文件名 |
created | %(created)f | 當前時間,用UNIX標準的表示時間的浮點數表示; 日誌事件發生的時間–時間戳,就是當時調用time.time()函數返回的值 |
relativeCreated | %(relativeCreated)d | 輸出日誌信息時的,自Logger創建以 來的毫秒數; 日誌事件發生的時間相對於logging模塊加載時間的相對毫秒數 |
msecs | %(msecs)d | 日誌事件發生事件的毫秒部分。logging.basicConfig()中用了參數datefmt,將會去掉asctime中產生的毫秒部分,可以用這個加上 |
5、日誌輸出格式
日誌的輸出格式可以認爲設置,默認格式爲下圖所示。
6、loggin 的四大組件
組件名稱 | 對應類名 | 功能描述 |
---|---|---|
日誌器 | Logger | 提供了應用程序可一直使用的接口 |
處理器 | Handler | 將logger創建的日誌記錄發送到合適的目的輸出 |
過濾器 | Filter | 提供了更細粒度的控制工具來決定輸出哪條日誌記錄,丟棄哪條日誌記錄 |
格式器 | Formatter | 決定日誌記錄的最終輸出格式 |
7、常用的配置方法
方法 | 描述 |
---|---|
Logger.setLevel() | 設置日誌器將會處理的日誌消息的最低嚴重級別 |
Logger.addHandler() | 和 Logger.removeHandler() 爲該logger對象添加 和 移除一個handler對象 |
Logger.addFilter() | 和 Logger.removeFilter() 爲該logger對象添加 和 移除一個filter對象 |
7.1 logger對象配置完成後,可以使用下面的方法來創建日誌記錄:
方法 | 描述 |
---|---|
Logger.debug(), Logger.info(), Logger.warning(), Logger.error(), Logger.critical() | 創建一個與它們的方法名對應等級的日誌記錄 |
Logger.exception() | 創建一個類似於Logger.error()的日誌消息 |
Logger.log() | 需要獲取一個明確的日誌level參數來創建一個日誌記錄 |
8、Handler類: 配置日誌輸出位置
輸出方向 | |
1、日誌文件 | |
2、標準輸出 | |
3、Email |
Handler.setLevel(lel):指定被處理的信息級別,低於lel級別的信息將被忽略
Handler.setFormatter():給這個handler選擇一個格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或刪除一個filter對象
Logger.addHandler()和Logger.removeHandler()從記錄器對象中添加和刪除處理程序對象。處理器詳見Handlers。
8.1 Handlers
應用程序代碼不應該直接實例化和使用Handler實例。因爲Handler是一個基類,它只定義了素有handlers都應該有的接口,同時提供了一些子類可以直接使用或覆蓋的默認行爲。下面是一些常用的Handler:
Handler | 描述 |
---|---|
logging.StreamHandler | 控制檯輸出,將日誌消息發送到輸出到Stream,如std.out, std.err或任何file-like對象。 |
logging.FileHandler | 將日誌消息發送到磁盤文件,默認情況下文件大小會無限增長 |
logging.handlers.RotatingFileHandler | 將日誌消息發送到磁盤文件,並支持日誌文件按大小切割,達到指定文件大小,重新生成文件,並重新命名 前面的文件 (caht.log.1、caht.log.2) |
logging.hanlders.TimedRotatingFileHandler | 將日誌消息發送到磁盤文件,並支持日誌文件按時間切割 |
logging.handlers.HTTPHandler | 將日誌消息以GET或POST的方式發送給一個HTTP服務器 |
logging.handlers.SMTPHandler | 將日誌消息發送給一個指定的email地址 |
logging.NullHandler | 該Handler實例會忽略error messages,通常被想使用logging的library開發者使用來避免’No handlers could be found for logger XXX’信息的出現。 |
9、自定義配置
我們知道創建一個 Logger 對象所需的配置了,以前直接硬編碼在程序中配置對象,配置還可以從字典類型的對象和配置文件獲取。打開 logging.config Python 文件,可以看到其中的配置解析轉換函數。
9.1、硬編碼配置
def log2():
LOG_FORMAT = "%(asctime)s %(name)s %(filename)s %(funcName)s %(levelname)s %(pathname)s %(message)s " # 配置輸出日誌格式
DATE_FORMAT = '%Y-%m-%d %H:%M:%S %a ' # 配置輸出時間的格式,注意月份和天數不要搞亂了
logging.basicConfig(level=logging.DEBUG,
format=LOG_FORMAT,
datefmt=DATE_FORMAT,
filename=r"./ab.log" # 有了filename參數就不會直接輸出顯示到控制檯,而是直接寫入文件
)
# 創建log 日誌信息
logging.debug("msg1")
logging.info("msg2")
logging.warning("msg3")
logging.error("msg4")
logging.critical("msg5")
import logging
def log():
#創建logger,如果參數爲空則返回root logger
logger = logging.getLogger("nick")
logger.setLevel(logging.DEBUG) #設置logger日誌等級
#這裏進行判斷,如果logger.handlers列表爲空,則添加,否則,直接去寫日誌
if not logger.handlers:
#創建兩個handler
fh = logging.FileHandler("test.log",encoding="utf-8")
ch = logging.StreamHandler()
#設置輸出日誌格式
formatter = logging.Formatter(
fmt="%(asctime)s %(name)s %(filename)s %(message)s",
datefmt="%Y/%m/%d %X"
)
#爲兩個handler指定輸出格式
fh.setFormatter(formatter)
ch.setFormatter(formatter)
#爲logger添加的日誌處理器
logger.addHandler(fh)
logger.addHandler(ch)
return logger #直接返回logger
logger = log()
logger.warning("泰拳警告")
logger.info("提示")
logger.error("錯誤")
logger.debug("查錯")
9.2、從配置文件中獲取配置信息:
常見的配置文件有 ini 格式、yaml 格式、JSON 格式,或者從網絡中獲取都是可以的,只要有相應的文件解析器解析配置即可,下面只展示了 ini 格式和 yaml 格式的配置。
注意: 在使用配置文件的時候不能出現中文,否則會報錯。在使用的時候需要將配置文件中的中文去掉
UnicodeDecodeError: 'gbk' codec can't decode byte 0xab in position 492: illegal multibyte sequence
9.2.1 int 文件
test.ini 文件
[loggers] # loggers 對象列表
keys=root,main
[handlers] # handlers 對象列表
keys=consoleHandler,fileHandler
[formatters] # formatters 對象列表
keys=fmt
[logger_root]# 配置 logger_root :設置日誌級別、輸出位置(控制檯和文件)
level=DEBUG
handlers=consoleHandler,fileHandler
[logger_main]# 配置 logger_main :設置日誌級別、輸出位置(文件)、除開root logger 對象其餘的logger對象 qualname 參數不能少
level = DEBUG
handlers = fileHandler
qualname=main
propagate=0
[handler_consoleHandler] # consoleHandler 控制器輸出方向、級別、輸出格式、參數
class = StreamHandler
level = DEBUG
formatter = fmt
args = (sys.stdout,)
[handler_fileHandler]# fileHandler 控制器輸出方向、級別、輸出格式、參數
class = logging.handlers.RotatingFileHandler
level = DEBUG
formatter = fmt
args = ('test.log', 'a', 10000, 3,)
#args = ("test.log", mode="w", maxBytes=1000, backupCount=3, encoding="utf-8")
[formatter_fmt]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
testinit.py 文件
import logging.config
# 配置 root logger
logging.config.fileConfig(fname='test.ini', disable_existing_loggers=False)
# 獲取logger 對象
logger = logging.getLogger("sampleLogger")
# 創建日誌信息
logger.info("HELLO 智障")
9.2.2 conf文件
testlog.conf 文件
[loggers] # loggers 對象列表
keys=root,main
[handlers] # handlers 對象列表
keys=consoleHandlers,fileHandlers
[formatters] # formatters 列表
keys=fmt
[logger_root]
level=DEBUG
handlers=consoleHandlers,fileHandlers
[logger_main] # main logger
level = DEBUG
handlers = fileHandlers
qualname=main
propagate=0
[handler_consoleHandlers]# consoleHandlers 指定控制器的輸出方向、級別、輸出格式、參數
class = StreamHandler
level = DEBUG
formatter = fmt
args = (sys.stdout,)
[handler_fileHandlers]]# 循環日誌文件 以文件大小來 分割# 每隔 1000 Byte 劃分一個日誌文件,備份文件爲 3 個
class = logging.handlers.RotatingFileHandler
level = DEBUG
formatter = fmt
args = ('test.log', 'a', 10000, 3, 'UTF-8')
[formatter_fmt] # fmt 格式
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
testinit.py 文件
import logging.config
# 讀取配置文件 # 採用配置文件
logging.config.fileConfig("testlog.conf")
# 創建logger
logger = logging.getLogger('main')
# 日誌生成
logger.debug(' Hello tom')
擴展
日誌文件按照時間劃分或者按照大小劃分
如果將日誌保存在一個文件中,那麼時間一長,或者日誌一多,單個日誌文件就會很大,既不利於備份,也不利於查看。我們會想到能不能按照時間或者大小對日誌文件進行劃分呢?答案肯定是可以的,並且還很簡單,logging 考慮到了我們這個需求。logging.handlers 文件中提供了 TimedRotatingFileHandler 和 RotatingFileHandler 類分別可以實現按時間和大小劃分。打開這個 handles 文件,可以看到還有其他功能的 Handler 類,它們都繼承自基類 BaseRotatingHandler。
TimedRotatingFileHandler 類構造函數
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
RotatingFileHandler 類的構造函數
def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)
示例代碼如下:
# 每隔 1000 Byte 劃分一個日誌文件,備份文件爲 3 個
file_handler = logging.handlers.RotatingFileHandler("test.log", mode="w", maxBytes=1000, backupCount=3, encoding="utf-8")
# 每隔 1小時 劃分一個日誌文件,interval 是時間間隔,備份文件爲 10 個
handler2 = logging.handlers.TimedRotatingFileHandler("test.log", when="H", interval=1, backupCount=10)