python的logging模塊詳解

日誌級別

>>>import logging
>>>logging.NOTSET
0
>>>logging.DEBUG
10
>>>logging.INFO
20
>>>logging.WARN
30
>>>logging.ERROR
40
>>>logging.CRITICAL
50
>>>logging._levelNames
{0:'NOTSET', 10: 'DEBUG', 'WARN': 30, 20: 'INFO', 'ERROR': 40, 'DEBUG': 10, 30:'WARNING', 'INFO': 20, 'WARNING': 30, 40: 'ERROR', 50: 'CRITICAL', 'CRITICAL':50, 'NOTSET': 0}


從以上可以看出logging模塊輸出日誌默認共有6個級別,級別大小依次是CRITICAL>ERROR> WARN> INFO> DEBUG> NOTSET

 

日誌默認輸出級別

[root@ju tmp]# cat log.py 
#!/usr/bin/envpython
importlogging
logging.debug('Thisis debug level')
logging.info('Thisis info level')
logging.warning('Thisis warning level')
logging.error('Thisis error level')
logging.critical('Thisis critical level')


輸出結果如下:

[root@ju tmp]# python log.py 
WARNING:root:Thisis warning level
ERROR:root:Thisis error level
CRITICAL:root:Thisis critical level

 

從執行結果可以看出,logging模塊的日誌輸出級別默認是warning級別。

 

自定義日誌格式並輸出到文件

日誌的輸出格式和方式可以通過logging.basicConfig函數配置。

#!/usr/bin/envpython
#coding=utf-8
importlogging
logging.basicConfig(level=logging.DEBUG,
    format='%(asctime)s%(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
    datefmt='%a, %d %b %Y %H:%M:%S',
    filename='test.log',
    filemode='a')
'''
可見在logging.basicConfig()函數中可通過具體參數來更改logging模塊默認行爲,可用參數有:
filename:          指定日誌文件名
filemode:          指定日誌文件的打開模式,'w'覆蓋或'a'追加
format:            定義輸出的格式和內容
datefmt:           指定時間格式,同time.strftime()
level:            設置rootlogger的日誌級別
stream:            用指定的stream創建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件,默認爲sys.stderr。若同時列出了filename和stream兩個參數,則stream參數會被忽略。
'''
logging.debug('Thisis debug level')
logging.info('Thisis info level')
logging.warning('Thisis warning level')
logging.error('Thisis error level')
logging.critical('Thisis critical level')


[root@ju python_moudle]# python logtest.py 
 
輸出結果如下:
[root@ju python_moudle]# cat test.log 
Mon, 15Jun 2015 03:48:01 logtest.py[line:10] DEBUG This is debug level
Mon, 15Jun 2015 03:48:01 logtest.py[line:11] INFO This is info level
Mon, 15Jun 2015 03:48:01 logtest.py[line:12] WARNING This is warning level
Mon, 15Jun 2015 03:48:01 logtest.py[line:13] ERROR This is error level
Mon, 15Jun 2015 03:48:01 logtest.py[line:14] CRITICAL This is critical level


自定義日誌格式並輸出到控制檯

[root@ju python_moudle]# cat logtest.py 
#!/usr/bin/envpython
#coding=utf-8
importlogging
#定義一個StreamHandler,將INFO級別或更高的日誌信息打印到標準錯誤,並將其添加到當前的日誌處理對象#
console= logging.StreamHandler()  #StreamHandler輸出到控制檯,FileHandler輸出到文件.
console.setLevel(logging.WARN)
formatter= logging.Formatter('%(name)-8s: %(levelname)-12s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
 
logging.debug('Thisis debug level')
logging.info('Thisis info level')
logging.warning('Thisis warning level')
logging.error('Thisis error level')
logging.critical('Thisis critical level')


輸出結果如下:

[root@ju python_moudle]# python logtest.py 
root    : WARNING      This is warning level
root    : ERROR         Thisis error level
root    : CRITICAL      Thisis critical level


Handlers

handler對象負責發送相關的信息到指定目的地。Python的日誌系統有多種Handler可以使用。StreamHandler可以把信息輸出到控制檯,FileHandler可以把信息輸出到文件,還有些 Handler可以把信息發送到網絡上。如果覺得不夠用,還可以編寫自己的Handler。可以通過addHandler()方法添加多個多handler

Handler.setLevel(levelname):指定被處理的信息級別,低於levelname級別的信息將被忽略

Handler.setFormatter():給這個handler指定一個格式

Handler.addFilter(filt)Handler.removeFilter(filt):新增或刪除一個filter對象

 

Logging模塊中有多中可用的Handler

logging.StreamHandler                 可以向類似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息

logging.FileHandler                用於向一個文件輸出日誌信息

logging.handlers.RotatingFileHandler  類似於上面的FileHandler,但是它可以管理文件大小。當文件達到一定大小之後,它會自動將當前日誌文件改名,然後創建一個新的同名日誌文件繼續輸出

logging.handlers.TimedRotatingFileHandlerRotatingFileHandler類似,不過,它沒有通過判斷文件大小來決定何時重新創建日誌文件,而是間隔一定時間就自動創建新的日誌文件

logging.handlers.SocketHandler      使用TCP協議,將日誌信息發送到網絡。

logging.handlers.DatagramHandler    使用UDP協議,將日誌信息發送到網絡。

logging.handlers.SysLogHandler      日誌輸出到syslog

logging.handlers.NTEventLogHandler  遠程輸出日誌到Windows NT/2000/XP的事件日誌

logging.handlers.SMTPHandler       遠程輸出日誌到郵件地址

logging.handlers.MemoryHandler     日誌輸出到內存中的制定buffer

logging.handlers.HTTPHandler       通過"GET""POST"遠程輸出到HTTP服務器

各個Handler的具體用法可查看參考書冊:

https://docs.python.org/2/library/logging.handlers.html#module-logging.handlers

 

 

Formatters

Formatter對象設置日誌信息最後的規則、結構和內容,默認的時間格式爲%Y-%m-%d%H:%M:%S,下面是Formatter常用的一些信息。

%(name)s                  Logger的名字

%(levelno)s:           打印日誌級別的數值

%(levelname)s:        打印日誌級別名稱

%(pathname)s:        打印當前執行程序的路徑,其實就是sys.argv[0]

%(filename)s:         打印當前執行程序名

%(module)s               調用日誌輸出函數的模塊名

%(funcName)s:      打印日誌的當前函數

%(lineno)d:           打印日誌的當前行號

%(created)f                當前時間,用UNIX標準的表示時間的浮點數表示

%(relativeCreated)d    輸出日誌信息時的,自Logger創建以來的毫秒數

%(asctime)s:          打印日誌的時間

%(thread)d:           打印線程ID

%(threadName)s:      打印線程名稱

%(process)d:          打印進程ID

%(message)s:         打印日誌信息

 

getLogger模塊詳解

logging.getLogger()時參數的格式類似於“arg1.arg2.arg3”,上代碼:

[root@ju python_moudle]# cat logtest.py 
#!/usr/bin/envpython
#coding=utf-8
importlogging
#創建一個logger     
logroot= logging.getLogger()
 
log1 =logging.getLogger('L1')
log1.setLevel(logging.DEBUG)
 
log2 =logging.getLogger('L1.L2')
log2.setLevel(logging.INFO)
 
log3 = logging.getLogger('L1.L2.L3')
log3.setLevel(logging.WARNING)
#創建一個handler,用於輸出到控制檯
ch =logging.StreamHandler()   
#定義handler的輸出格式formatter     
formatter= logging.Formatter('%(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
#給logger添加handler 
logroot.addHandler(ch)
log1.addHandler(ch)
log2.addHandler(ch)
log3.addHandler(ch)
#打印日誌     
logroot.debug('logrootdebug message')   
logroot.info('logrootinfo message')   
logroot.warning('logrootwarning message')   
logroot.error('logrooterror message')   
logroot.critical('logrootcritical message')   
   
log1.debug('log1debug message')   
log1.info('log1info message')   
log1.warning('log1warning message')   
log1.error('log1error message')   
log1.critical('log1critical message')   
   
log2.debug('log2debug message')   
log2.info('log2info message')   
log2.warning('log2warning message')   
log2.error('log2error message')   
log2.critical('log2critical message')   
   
log3.debug('log3debug message')   
log3.info('log3info message')   
log3.warning('log3warning message')   
log3.error('log3error message')   
log3.critical('log3critical message')


輸出結果如下:

[root@jupython_moudle]# python logtest.py 
root -WARNING - logroot warning message
root -ERROR - logroot error message
root -CRITICAL - logroot critical message
L1 -DEBUG - log1 debug message
L1 -DEBUG - log1 debug message
L1 -INFO - log1 info message
L1 -INFO - log1 info message
L1 -WARNING - log1 warning message
L1 -WARNING - log1 warning message
L1 -ERROR - log1 error message
L1 -ERROR - log1 error message
L1 -CRITICAL - log1 critical message
L1 -CRITICAL - log1 critical message
L1.L2 -INFO - log2 info message
L1.L2 -INFO - log2 info message
L1.L2 -INFO - log2 info message
L1.L2 -WARNING - log2 warning message
L1.L2 -WARNING - log2 warning message
L1.L2 -WARNING - log2 warning message
L1.L2 -ERROR - log2 error message
L1.L2 -ERROR - log2 error message
L1.L2 -ERROR - log2 error message
L1.L2 -CRITICAL - log2 critical message
L1.L2 -CRITICAL - log2 critical message
L1.L2 -CRITICAL - log2 critical message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message

 

由以上輸出結果可以看出rootlog的每個輸出分別打印1次,log1對應的輸出分別打印了2次,log2對應的輸出打印了3次,log3打印4次。logger = logging.getLogger()顯示的創建了root Logger,這是因爲logger實例之間的“父子關係”,rootlogger處於最頂層,log1是第二層,log2是第三層,以此類推。所以在把消息分發給它們的handler進行處理時也會傳遞給所有的祖先Logger處理。

 

現在把以下兩行註釋,再輸出

logroot.addHandler(ch)   
log1.addHandler(ch)

 

輸出結果如下:

[root@ju python_moudle]# python logtest.py 
Nohandlers could be found for logger "root"
L1.L2 -INFO - log2 info message
L1.L2 -WARNING - log2 warning message
L1.L2 -ERROR - log2 error message
L1.L2 -CRITICAL - log2 critical message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message

這時候可以看到log2就變成最頂層的節點,log3handler時還是要傳遞給log2處理一遍,所以輸出兩遍。

 

使用filter設置過濾器

限制只有滿足過濾規則的日誌纔會輸出。比如我們定義了filter = logging.Filter('L1.L2.L3'),並將這個Filter添加到了一個Handler上,則使用該HandlerLogger中只有名字帶a.b.c前綴的Logger才能輸出其日誌。看代碼:

[root@jupython_moudle]# cat logtest.py 
#!/usr/bin/envpython
#coding=utf-8
importlogging
 
#創建一個logger     
logroot= logging.getLogger()   
log1 =logging.getLogger('L1')   
log1.setLevel(logging.DEBUG)   
log2 =logging.getLogger('L1.L2')   
log2.setLevel(logging.INFO)   
log3 =logging.getLogger('L1.L2.L3')   
log3.setLevel(logging.WARNING)   
#再創建一個handler,用於輸出到控制檯     
ch =logging.StreamHandler()   
#定義handler的輸出格式formatter     
formatter= logging.Formatter('%(name)s - %(levelname)s - %(message)s')   
ch.setFormatter(formatter)
#定義filter
f =logging.Filter('L1.L2.L3')
ch.addFilter(f)
#給logger添加handler     
logroot.addHandler(ch)   
log1.addHandler(ch)   
log2.addHandler(ch)   
log3.addHandler(ch)   
#打印日誌     
logroot.debug('logrootdebug message')   
logroot.info('logrootinfo message')   
logroot.warning('logrootwarning message')   
logroot.error('logrooterror message')   
logroot.critical('logrootcritical message')   
   
log1.debug('log1debug message')   
log1.info('log1info message')   
log1.warning('log1warning message')   
log1.error('log1error message')   
log1.critical('log1critical message')   
   
log2.debug('log2debug message')   
log2.info('log2info message')   
log2.warning('log2warning message')   
log2.error('log2error message')   
log2.critical('log2critical message')   
   
log3.debug('log3debug message')   
log3.info('log3info message')   
log3.warning('log3warning message')   
log3.error('log3error message')   
log3.critical('log3critical message')


輸出結果如下:

[root@ju python_moudle]# python logtest.py 
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message


由輸出結果可以看到,正如前面所說,只輸出以L1.L2.L3開頭的logger了。但是爲HandlerFilter後只要使用了該HandlerLogger都會受影響。而爲Logger單獨添加Filter只會影響到自身。看代碼:

#定義filter
f =logging.Filter('L1.L2')
#ch.addFilter(f)                   #把此行註釋
#給logger添加filter和handler    
logroot.addHandler(ch)
log1.addFilter(f)                  #給log1加上filter
log1.addHandler(ch)
log2.addFilter(f)                  #給log2加上filter
log2.addHandler(ch)
log3.addHandler(ch)


輸出結果如下:

[root@ju python_moudle]# python logtest.py 
root -WARNING - logroot warning message
root -ERROR - logroot error message
root -CRITICAL - logroot critical message
L1.L2 -INFO - log2 info message
L1.L2 -INFO - log2 info message
L1.L2 -INFO - log2 info message
L1.L2 -WARNING - log2 warning message
L1.L2 -WARNING - log2 warning message
L1.L2 -WARNING - log2 warning message
L1.L2 -ERROR - log2 error message
L1.L2 -ERROR - log2 error message
L1.L2 -ERROR - log2 error message
L1.L2 -CRITICAL - log2 critical message
L1.L2 -CRITICAL - log2 critical message
L1.L2 -CRITICAL - log2 critical message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- WARNING - log3 warning message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- ERROR - log3 error message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message
L1.L2.L3- CRITICAL - log3 critical message


由以上輸出可以看到rootlog並未受影響,log1由於未匹配到所以沒有輸出,log2匹配到說以輸出,log3未定義filter也可能輸出。

 

通過logging.config模塊配置日誌

[root@jupython_moudle]# cat log.conf 
[loggers]
keys=root,TestLogger
 
[handlers]
keys=consoleHandler
 
[formatters]
keys=TestFormatter
 
[logger_root]
level=DEBUG
handlers=consoleHandler
 
[logger_TestLogger]
level=DEBUG
handlers=consoleHandler
qualname=TestLogger
propagate=0
 
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=TestFormatter
args=(sys.stdout,)
 
[formatter_TestFormatter]
format=%(asctime)-12s%(name)-12s %(levelname)-12s %(message)s
datefmt='%a,%d %b %Y %H:%M:%S'


[root@jupython_moudle]# cat logtest.py 
#!/usr/bin/envpython
#coding=utf-8
importlogging
importlogging.config
 
logging.config.fileConfig('log.conf')  #使用log.conf配置文件
 
#創建日誌
LOG =logging.getLogger("TestLogger")
 
LOG.debug('Thisis debug level')
LOG.info('Thisis info level')
LOG.warning('Thisis warning level')
LOG.error('Thisis error level')
LOG.critical('Thisis critical level')


結果輸出如下:

[root@ju python_moudle]# python logtest.py 
'Mon, 15Jun 2015 08:04:49' TestLogger  DEBUG        This is debug level
'Mon, 15Jun 2015 08:04:49' TestLogger   INFO         This is info level
'Mon, 15Jun 2015 08:04:49' TestLogger  WARNING      This is warning level
'Mon, 15Jun 2015 08:04:49' TestLogger  ERROR        This is error level
'Mon, 15Jun 2015 08:04:49' TestLogger  CRITICAL     This is criticallevel


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章