日志基础
参考:https://docs.python.org/3/howto/logging.html
4 个核心组件
组件 | 说明 |
---|---|
logger | 程序用来记录日志 |
handler | 将日志发送到合适的目的地 |
filter | 决定哪些日志被输出 |
formatter | 日志以何种格式输出 |
logger
常用配置方法
Logger.getLever()
要处理的最低级别消息(内置级别中,debug 是最低级而 critical 是最高级)Logger.addHandler()
和Logger.removeHandler()
添加或移除 handler 对象Logger.addFilter()
和Logger.removeFilter()
添加或移除 filter 对象
无需在每个 logger 上调用这些配置方法
- logger 有个 生效级别 的概念。如果一个 logger 未明确设定级别,则会继承其父 logger 的级别;若父 logger 也没有设定级别,会继续查找更上层的 logger 的级别,直到
root
looger。root
logger 默认的级别是WARNING
- handler 同理,只需要设定最顶级的 logger 的 handler 即可
创建日志
Logger.debug()
Logger.info()
Logger.warning()
Logger.error()
Logger.critical()
不解释Logger.exception()
和Logger.error()
相似,不同之处在于Logger.exception()
输出异常堆栈,注意:仅在异常处理时调用此方法Logger.log()
该方法要指定一个明确的日志级别,可用于自定义的的日志级别
getLogger()
通过 logger 名字反映包/模块层次及事件在哪发生。
logger = logging.getLogger(__name__)
- 如果不指定名字,则为
root
- 用相同的名字多次调用该方法返回的是同一个日志对象
- 如果
foo
是一个 logger 的名字,那么foo.bar
foo.bar.baz
foo.bam
都是foo
的后代
handler
handler,把日志发送到关联的目的地的东东。logger.addHandler(),可以添加 0 个或多个 handler
- 可以把日志记录到文件,http GET/POST,email,队列,或操作系统特定的日志机制,诸如 syslog 或 windows NT 事务日志。通过
handler
类来设定目的地 - 可以创建自己的
handler
- 默认情况下,没有设定目的地。
- 可以用
basicConfig()
指定,诸如 console(控制台) 或 file(文件)。调用info()
,debug()
等方法时,会自动检测有无设定目的地,如果没有设置,会将 console(控制台) 设置为目的地。
例如把所有日志发送到一个文件,高于 error 的日志发送到标准输出,cirtical 发送邮件
常用的方法
setLevel()
和 logger 的一样,指定一个最低级别。为什么要有 2 个setLevel()
logger.setLevel()
判断哪个级别的消息要发送到 handlerhandler.setLevel()
判断哪个消息将发送
setFormatter()
为 handler 选择一个 formatteraddFilter()
removeFilter()
设定 handler 的 filter
应用程序代码不应直接实例化和使用 Handler。相反,Handler 是一个基类,它定义了所有 handler 应该具有的接口,并建立了一些子类可以使用(或重写)的默认行为
内置的 handler
python 内置了 Hanlder 的一些子类,参考:https://docs.python.org/3/howto/logging.html#useful-handlers
StreamHandler
发送消息到 stream (类文件对象) 可以理解为就是 控制台(console)FileHandler
发送消息到磁盘文件BaseRotatingHandler
这是 轮换日志 处理器的基类,不要直接用这个handler,用它的子类RotatingFileHandler
发送消息到磁盘文件,可以设定文件按最大尺寸进行轮换TimedRotatingFileHandler
发送消息到磁盘文件,并按时间轮换文件
SocketHandler
发送消息到 TCP/IP socketsDatagramHandler
发送消息到 UDP socketsSMTPHandler
发送消息到 email 地址SysLogHandler
可以远程发送日志到 unix 的 syslog 守护进程NTEventLogHandler
发送消息到 Windows NT/2000/XP 事务日志MemoryHandler
发送日志到内存缓冲区,该缓冲区有其持久化到磁盘的策略HTTPHandler
用 GET/POST 方法发送消息到一个 HTTP 服务器WatchedFileHandler
仅用于类 unix 系统,会观察日志文件,如果日志文件发生改变,会关闭并用文件名重新打开文件QueueHandler
发送消息到队列,例如一些多进程模块NullHandler
不处理错误日志。库开发者可以用给这个 handler,这样可以避免库的使用者未配置 logging 时出现的 "No handlers could be found for logger XXX" 消息
注意
NullHandler
,StreamHandler
andFileHandler
在 logging 包,其他子类在 logging.handlers 包
formatter
basicConfig()
默认格式如下
severity:logger name:message
不同于 Handler,可以直接实例化 Formatter 对象,构造器接收 3 个可选参数:消息格式,时间格式,样式
logging.Formatter.__init__(fmt=None, datefmt=None, style='%')
- 消息格式 如果未设定,使用原始的消息
- 时间格式 如果未设定,则为
%Y-%m-%d %H:%M:%S
- 样式
%
,{
,$
之一,若未设定则为%
(应该是设定一个指示变量的占位符)
下面的消息格式串将按顺序记录时间、日志级别、消息内容
'%(asctime)s - %(levelname)s - %(message)s'
要设定格式,参考 Formatter Objects
formatter 用一个用户设定的函数来将日志创建时间转换为 tuple。默认情况下使用 time.localtime()
,若要改变,设定 formatter 的 converter
属性为一个和 time.localtime()
或 time.gmttime()
参数相同的函数,如果要修改所有 formatter 的 converter
属性,则改变 Formatter
的 converter
属性
配置 logging
有 3 种配置方法
- 在 python 代码里创建 logger, handler 和 formatter 并调用上述的配置方法
- 创建一个配置文件,使用
fileConfig()
方法来加载,配置文件格式见 file format - 创建一个配置 dict 发送给
dictConfig()
方法
对于 2,3 参考 配置函数
配置示例
用代码配置
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')
在命令行运行并输出
$ python simple_logging_module.py
2005-03-19 15:10:26,618 - simple_example - DEBUG - debug message
2005-03-19 15:10:26,620 - simple_example - INFO - info message
2005-03-19 15:10:26,695 - simple_example - WARNING - warn message
2005-03-19 15:10:26,697 - simple_example - ERROR - error message
2005-03-19 15:10:26,773 - simple_example - CRITICAL - critical message
用配置文件
配置文件 logging.conf
[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=
代码
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')
命令行运行并输出
$ python simple_logging_config.py
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