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实例的方式更加合理,把配置和代码分离了,更容易扩展,应该作为实际项目中推荐的使用方式。
参考: