python logging模塊中各個基礎組件
在項目中,我們可能需要定義不同的日誌格式,有時需要定位到某一行,有的就不需要,並且根據情況要篩選不同的日誌等級,例如,生產環境就不需要打印 DEBUG
級別的日誌。這就涉及到需要多個日誌模型。
python中定義了基本的日誌組件讓我們可以去組裝和自定義以實現日誌模型,功能包括日誌信息過濾(脫敏)、篩選日誌等級等等。這些組件包括:
logging.Logger
, logging.Handler
, logging.Formatter
, logging.Filter
, logging.LogRecord
, LoggerAdapter
。
1. logging.Logger
在 python 中獲取 Logger
實例,一般是通過 logging.getLogger(name)
這個方法來獲得,並且針對單個 name
,不管獲得多少次,都是同一個實例。
1.1 Logger
的方法:
setLevel
: 設置最低的日誌輸出的等級。在3.2版本之後可以接受INFO
或是20
這樣的字符串或是整型類型信息。- 記錄日誌的方法,分別有對應的等級:
debug
、info
、warn
、error
、warning
、exception
、critical
、fatal
、log
Handler
添加與移除:addHandler
,removeHandler
- 生成
LogRecord
:makeRecord
import logging
logger = logging.getLogger('test')
logger.setLevel('INFO')
logger.debug('test logger debug')
logger.info('test logger')
輸出爲: No handlers could be found for logger "test"
, 從結果看來,還缺少Handelr實例。
2. logging.Handler
實際來處理日誌記錄的類, 用以做一些特殊邏輯上的操作。如記錄到文件、上傳日誌等等。
主要的方法有:
setLevel
setFormatter
format
: 格式化日誌。- 過濾器:
addFilter
,removeFilter
- 處理日誌信息流程:
handle
,handleError
,emit
, 最終的邏輯在emit
中,handle
的邏輯是會加上鎖,調用emit
3. logging.Formatter
格式化日誌記錄的類, 主要方法有:
format(record)
- 處理時間信息:
formatTime
- 格式化異常信息:
formatException
4. loggingFilter
Filter
的實例,能被用在 Handler
和 Logger
這個兩個類的實例中。
該類的方法時 filter(record)
: 用來決定指定的 record
是否可以被記錄, 能被記錄返回True, 否則爲False,並且,我們可以用來過濾一些參數信息,將敏感信息脫敏。
5. logging.LogRecord
用來記錄一條日誌中的所有信息和需要的信息。
6. 常用生成自己所需 Logger
的組合方式:
-
使用代碼,直接使用
Logger
、Handler
等實例,進行組合:import logging logger = logging.getLogger('test') logger.setLevel('INFO') handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) logger.debug('debug message') logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message')
輸出爲:
2019-01-05 17:11:46,286 - test - INFO - info message 2019-01-05 17:11:46,286 - test - WARNING - warn message 2019-01-05 17:11:46,286 - test - ERROR - error message 2019-01-05 17:11:46,286 - test - CRITICAL - critical message
-
使用配置文件,加載配置文件,
fileConfig()
配置文件信息爲:
import logging import logging.config logging.config.fileConfig('logging.conf') # create logger logger = logging.getLogger('simpleExample') # 'application' code logger.debug('debug message') logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message')
[loggers] keys=root,simpleExample [handlers] keys=consoleHandler [formatters] keys=simpleFormatter [logger_root] level=DEBUG handlers=consoleHandler [logger_simpleExample] level=DEBUG handlers=consoleHandler qualname=simpleExample propagate=0 [handler_consoleHandler] class=StreamHandler level=DEBUG formatter=simpleFormatter args=(sys.stdout,) [formatter_simpleFormatter] format=%(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt=
輸出爲:
2005-03-19 15:38:55,977 - simpleExample - DEBUG - debug message 2005-03-19 15:38:55,979 - simpleExample - INFO - info message 2005-03-19 15:38:56,054 - simpleExample - WARNING - warn message 2005-03-19 15:38:56,055 - simpleExample - ERROR - error message 2005-03-19 15:38:56,130 - simpleExample - CRITICAL - critical message
-
使用
dict
類型的變量進行配置,dictConfig()
.LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(message)s' }, }, 'filters': { 'special': { '()': 'project.logging.SpecialFilter', 'foo': 'bar', } }, 'handlers': { 'null': { 'level':'DEBUG', 'class':'django.utils.log.NullHandler', }, 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', 'formatter': 'simple' }, 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'filters': ['special'] } }, 'loggers': { 'django': { 'handlers':['null'], 'propagate': True, 'level':'INFO', }, 'django.request': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': False, }, 'myproject.custom': { 'handlers': ['console', 'mail_admins'], 'level': 'INFO', 'filters': ['special'] } } }
以上的配置 Logger
方案中,使用配置文件或是dict實例的方式更加合理,把配置和代碼分離了,更容易擴展,應該作爲實際項目中推薦的使用方式。
參考: