Python的 logging
模塊提供了靈活的日志處理相關功能, 可以用來追蹤程序運行的情況。
logging
模塊提供了一系列標准的日志等級: DEBUG, INFO, WARNING, ERROR, CRITICAL
, 顧名思義可以大致看出它們各自的使用情況。 logging
模塊設置的默認等級時 WARNING
, 這意味著默認情況下,日志級別為 WARNING, ERROR, CRITICAL
的日志會被記錄,而 DEBUG, INFO
的日志會被忽略。
不同等級的value值如下,只有當value大於 logger
的值才會記錄日志。
Level Value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
UNSET 0
下面看一個簡單的官方文檔上的例子:
import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything
輸出如下:
WARNING:root:Watch out!
可以看到info記錄的信息沒有輸出,這是因為默認輸出級別不低於WARNING級別的。
logging
支持輸出日志到文件,參考下面示例:
import logging
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
其中level是指的記錄等級, 輸出如下:
DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too
logger是logging模塊提供的日志類 Logger
的實例,它暴露出接口可以直接供程序調用。
每個實例都有一個名字,並且示例間有類之間那種繼承關系,根據logger的名字來區分,比如叫"scan"的logger是叫"scan.text"和"scan.html"的父類(沒錯,他們是以點號錯分隔符)。
所有logger共同的父類是 root
, 就是上面示例中的中間那個默認的root。 basicConfig
默認的輸出格式為: severity:logger name:message
。
logger的通過 logging.getLogger(name)
來創建,有種在包裡命名的慣用做法是:
logger = logging.getLogger(__name__)
這樣的好處是可以從logger的名字清楚的看到記錄的來源。
handlers
承擔 logging
模塊裡負責處理合適的信息到不同的地方的角色,下面通過設置一個RotatingFileHandler來展示handler的特性。
有時候需要創建多個輪轉日志,每個日志保存一定長度的內容,最多保留一定數量的日志,其余的丟棄,這種情況下,可以定義 RotatingFileHandler
來實現:
logging_rotatingfile_example.py
import glob
import logging
import logging.handlers
LOG_FILENAME = 'logging_rotatingfile_example.out'
# Set up a specific logger with our desired output level
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)
# Add the log message handler to the logger
handler = logging.handlers.RotatingFileHandler(
LOG_FILENAME,
maxBytes=20,
backupCount=5,
)
my_logger.addHandler(handler)
# Log some messages
for i in range(20):
my_logger.debug('i = %d' % i)
# See what files are created
logfiles = glob.glob('%s*' % LOG_FILENAME)
for filename in logfiles:
print(filename)
運行輸出如下:
logging_rotatingfile_example.out
logging_rotatingfile_example.out.1
logging_rotatingfile_example.out.2
logging_rotatingfile_example.out.3
logging_rotatingfile_example.out.4
logging_rotatingfile_example.out.5
當日志內容達到定義的 maxBytes
時,會自動重命名文件後加上後綴".1",如果已經存在後續的".1",".2"等則自動重命名他們向後加1,最後最多只保留 backupCount
定義數量的日志文件。
其它有用的handler參見這裡。
Formatters
可以用來控制日志輸出的格式,參考下面的示例:
import logging
# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
輸出如下:
2016-11-27 23:18:51,128 - simple_example - DEBUG - debug message
2016-11-27 23:18:51,128 - simple_example - INFO - info message
2016-11-27 23:18:51,128 - simple_example - WARNING - warn message
2016-11-27 23:18:51,128 - simple_example - ERROR - error message
2016-11-27 23:18:51,128 - simple_example - CRITICAL - critical message
可以看到 %(asctime)s - %(name)s - %(levelname)s - %(message)s
這裡對格式化輸出的影響。
其中默認的日期時間顯示的格式是ISO8601格式, 也可以自定義時間格式,如下面的例子:
import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')
輸出:
python test12.py
11/27/2016 11:22:41 PM is when this event was logged.
好有個比較有用的格式化參數時 %(lineno)d
, 顯示logger調用的時候所處的行數。具體的格式和作用可以參見這裡。
以 ERROR
的等級記錄日志,但和 DEBUG
等級一樣會輸出詳細的錯誤信息,通常用在exception處理中
Filters 是可以被handlers和loggers用來過濾日志的輸出的,因為用的不多,具體可參見文檔。
logging模塊是通過線程鎖保證線程安全的。
官方文檔上看到的logging流程圖,可以幫助理解日志記錄流程,參見這裡。
參見這裡。