日志的級別:
- DEBUG
- INFO
- WARNNING
- ERROR
- CRITICAL
作者代碼可以見 代碼
幾個重要的概念
- Logger:記錄器,是應(yīng)用程序直接使用的借口
- Handler處理器,將(記錄器)產(chǎn)生的日志記錄發(fā)送往合適的借口
- Filter:過濾器,提供更好的輸出控制,可以決定輸出哪些日志記錄
Logger
?Logger是一個樹級的結(jié)構(gòu),使用debug,info等前一定要創(chuàng)建Logger實(shí)例,即創(chuàng)建一個記錄器。如果沒有顯式的創(chuàng)建,默認(rèn)創(chuàng)建一個root logger,并應(yīng)用默認(rèn)的日志級別(WARN),處理器Handler(StreamHandler,即講日志信息打印輸出在標(biāo)準(zhǔn)的輸出上),和格式化器(默認(rèn)的格式是第一個簡單使用程序中輸出的樣式)。
#創(chuàng)建方法:
logger = logging.getLogger(logger_name)
?創(chuàng)建Logger實(shí)例后,可以使用如下的方法設(shè)置日志級別,增加處理器Handler。
- logger.setLevel(logging.DEBUG)
- logger.addHadnler(handler_name)
- logger.removeHandler(handler_name)
Handler處理器
?Handler的處理器類型有很多種,常見有三個,Streamhandler,FileHandler,NullHandler。
?創(chuàng)建StreamHandler后可以使用如下的方法設(shè)置日志級別(level),格式化器(Formatter),過濾器(Filter):
- ch.setLevel(logging.WARN)
- ch.setFormatter(formatter_name)
- ch.addFilter(filter_name)
- ch.removeFilter(filter_name)
#StreamHandler的創(chuàng)建方法:
sh = logging.StreamHandler(stream=None)
#FileHandler創(chuàng)建方法
fh = logging.FileHandler(filename,mode='a',encoding=None,delay=False)
#NullHandler創(chuàng)建方法
這玩意沒什么用,由庫開發(fā)者使用
Formatter格式化器
?使用Formatter對象設(shè)置日志信息的最后貴的,結(jié)構(gòu)和內(nèi)容,默認(rèn)的時(shí)間格式位%Y-%m-%d%H:%M:%S
#創(chuàng)建方法:
formatter = logging.Formatter(fmt=None,datafmt=None)
其中fmt是消息的格式化串,datafmt是日志字符串,如果不指定fmt將會使用%(message)s' 如果不指明datefmt將使ISO8601的日期格式。
Filter過濾器
?Handler和Logger都可以使用Filter完成比級別完成更復(fù)雜的過濾,F(xiàn)ilter基類僅允許指定Logger層次一下的事件,例如使用'A.B'初始化的Filter允許Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’等記錄的事件,logger‘A.BB’, ‘B.A.B’ 等就不行。 如果用空字符串來初始化,所有的事件都接受。
filter = logger.Filter(name=' ')
Logger Handler Filte Formatter幾種關(guān)系,該關(guān)系可以使用如下圖進(jìn)行描述:

由上圖可以知,Logger是一個樹形的結(jié)構(gòu),Logger可以包括多個Handler和Filter,一個Handler可以有多個Formatter和Filter,并且日志級別將會繼承。
Logging的工作流程

- 由上圖可以知道,如果使用者的代碼中產(chǎn)生了日志提交,首先進(jìn)行判斷登記等級是否大于Logger實(shí)例的等價(jià),如果小于,會拋棄這個日志,否則進(jìn)入下一步.
- 創(chuàng)建日志,使用注冊到Logger中的Filter進(jìn)行過濾,輪流進(jìn)行過濾,如果有一個把他過濾掉了,終止。否則等所有的過濾完成后進(jìn)入下一步。
-
- 日子繼續(xù)往下流
- 日志流向所有注冊在Logger中的Handlers,首先判斷等級夠不夠,接著判斷有沒有過濾器,都不能拒絕日志的話,將會格式化輸出(會產(chǎn)生額外的信息,比如在哪個文件那一行等)。
- 判斷日志能夠進(jìn)行傳播,如果可以并且有父類Logger,那么將會送入父類進(jìn)行處理。
幾種配置方式
#下面是一些模塊級別的函數(shù):
getLogger返回指定name的日志記錄器,name=None時(shí)候返回層級結(jié)構(gòu)總為根級別的記錄器,如果指定了name,name一般是用a. a.b a.b.c.d,這些名稱自定義
logging.getLogger(name=None)
logging.GetLoggerClass() 返回標(biāo)準(zhǔn)的Logger類
常見的logging.debug('')都是在根記錄器中產(chǎn)生消息
logging.disable(level=logging.CRITICAL),以為重載的形式會作用在所有的Logger,一般用來限制全局
logging.addLevelName(level,levelName) 自己定義一個等級對應(yīng)的名字,如30對應(yīng)一個MyDebug
logging.basicConfig(** kwags) 使用磨人的Formatte創(chuàng)建一個StreamHandler并加入根日志記錄起,如果沒有為跟記錄器定已處理程序,那么debug()等會自動調(diào)用basicConfig。如果根日志記錄器配置了處理程序,不執(zhí)行任何操作。
#logging.shutdown
?上述提到的支持一下參數(shù):
| 名字 | 功能 |
|---|---|
| filename | 指定日志輸出目標(biāo)文件的文件名,指定該設(shè)置項(xiàng)后日志信心就不會被輸出到控制臺了 |
| filemode | 指定日志文件的打開模式,默認(rèn)為'a'。需要注意的是,該選項(xiàng)要在filename指定時(shí)才有效 |
| format | 指定日志格式字符串,即指定日志輸出時(shí)所包含的字段信息以及它們的順序。logging模塊定義的格式字段下面會列出。 |
| datafmt | 指定日期/時(shí)間格式。需要注意的是,該選項(xiàng)要在format中包含時(shí)間字段%(asctime)s時(shí)才有效 |
| level | 指定日志器的日志級別 |
| stream | 可以指定日志輸出目標(biāo)stream,如sys.stdout、sys.stderr以及網(wǎng)絡(luò)stream。需要說明的是,stream和filename不能同時(shí)提供,否則會引發(fā) ValueError異常 |
| handlers | 該選項(xiàng)如果被指定,它應(yīng)該是一個創(chuàng)建了多個Handler的可迭代對象,這些handler將會被添加到root logger。需要說明的是:filename、stream和handlers這三個配置項(xiàng)只能有一個存在,不能同時(shí)出現(xiàn)2個或3個,否則會引發(fā)ValueError異常。 |
| encoding | |
| errors |
format參數(shù)中可能用到的格式化串:
- %(name)s Logger的名字
- %(levelno)s 數(shù)字形式的日志級別
- %(levelname)s 文本形式的日志級別
- %(pathname)s 調(diào)用日志輸出函數(shù)的模塊的完整路徑名,可能沒有
- %(filename)s 調(diào)用日志輸出函數(shù)的模塊的文件名
- %(module)s 調(diào)用日志輸出函數(shù)的模塊名
- %(funcName)s 調(diào)用日志輸出函數(shù)的函數(shù)名
- %(lineno)d 調(diào)用日志輸出函數(shù)的語句所在的代碼行
- %(created)f 當(dāng)前時(shí)間,用UNIX標(biāo)準(zhǔn)的表示時(shí)間的浮 點(diǎn)數(shù)表示
- %(relativeCreated)d 輸出日志信息時(shí)的,自Logger創(chuàng)建以 來的毫秒數(shù)
- %(asctime)s 字符串形式的當(dāng)前時(shí)間。默認(rèn)格式是 “2003-07-08 16:49:45,896”。逗號后面的是毫秒
- %(thread)d 線程ID??赡軟]有
- %(threadName)s 線程名??赡軟]有
- %(process)d 進(jìn)程ID??赡軟]有
- %(message)s用戶輸出的消息
一個例子
# -*- encoding:utf-8 -*-
import logging
# create logger
logger_name = "example"
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
# create file handler
log_path = "./log.log"
fh = logging.FileHandler(log_path)
fh.setLevel(logging.WARN)
# create formatter
fmt = "%(asctime)-15s %(levelname)s %(filename)s %(lineno)d %(process)d %(message)s"
datefmt = "%a %d %b %Y %H:%M:%S"
formatter = logging.Formatter(fmt, datefmt)
# add handler and formatter to logger
fh.setFormatter(formatter)
logger.addHandler(fh)
# print log info
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')```
##### 文件配置
配置文件logging.conf如下:
```[loggers]
keys=root,example01
[logger_root]
level=DEBUG
handlers=hand01,hand02
[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0
[handlers]
keys=hand01,hand02
[handler_hand01]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('log.log', 'a')
[formatters]
keys=form01,form02
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s```
使用程序logger.py如下:
```#!/usr/bin/python
# -*- encoding:utf-8 -*-
import logging
import logging.config
logging.config.fileConfig("./logging.conf")
# create logger
logger_name = "example"
logger = logging.getLogger(logger_name)
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')```
##### 字典配置
有興趣的童靴可以使用```logging.config.dictConfig(config)```編寫一個示例程序發(fā)給我,以提供給我進(jìn)行完善本文。
#### 監(jiān)聽配置