日志输出¶
日志在问题分析时必不可少,好的程序应该输出足够的日志信息。
那么,用 Python 语言开发程序时,如何输出日志呢?
—— logging 模块!
>>> import logging
>>> logging.warning('something wrong happended.')
WARNING:root:Something wrong happended.
>>> logging.info('seems good!')
这是一个入门级例子,导入 logging 模块后,调用 warning 方法即可输出警告信息。
日志级别¶
日志输出视轻重缓急,可分为多个级别。 例子还调用 info 方法输出一条普通信息,级别比警告信息低。 Python 支持的日志级别包括:
名称 |
数值 |
方法 |
含义 |
---|---|---|---|
CRITICAL |
logging.CRITICAL |
logger.critical |
严重错误 |
ERROR |
logging.ERROR |
logger.error |
错误 |
WARNING |
logging.WARNING |
logger.warning |
警告 |
INFO |
logging.INFO |
logger.info |
普通信息 |
DEBUG |
logging.DEBUG |
logger.debug |
调试信息 |
NOTSET |
logging.NOTSET |
未指定 |
注意到,例子中 info 输出的普通信息并没有真正打印到屏幕上, 这是因为默认的 logger 对象只输出较高级别日志。 为了输出想要的级别,我们需要自行定制 Logger 对象。
日志对象¶
Logger 对象通过 getLogger 方法创建:
>>> logger = logging.getLogger(__name__)
>>> logger.setLevel(logging.INFO)
>>> logger.info('you must be able to see me!')
INFO:__main__:you must be able to see me!
调用 Logger 对象 setLevel 方法设置日志输出级别,后续将忽略比该级别低的日志。 调用 debug 方法输出日志将被忽略:
>>> logger.debug('you cant see me now!')
更多定制方法,请查看 帮助文档 :
>>> help(logger)
日志处理器¶
前面几个例子,日志均输出到标准输出,因此我们可以在屏幕中看到。 当然了,日志还可以输出到文件,甚至可以通过网络发送出去,这都是通过 Handler 对象控制的。
标准输出¶
日志对象默认输出到标准输出,等价于:
logger_handler = logging.StreamHandler(sys.stdout)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(logger_handler)
可以进一步控制处理器可以输出的 日志级别 :
logger_handler = logging.StreamHandler(sys.stdout)
logger_handler.setLevel(logging.WARNING)
这样一来,只有不低于 WARNING 级别的日志才会被该处理器处理。 需要注意的是, Logger 对象以及 Handler 对象级别同时影响日志输出行为。
文件¶
相比标准输出,将日志输出到文件更为妥当,文件可以保留一定的历史待查。
日志格式¶
采用默认格式输出的日志非常丑陋,信息量也不够,甚至连时间都没有! 因此,需要根据应用需求,灵活调整日志输出格式。 为 Handler 对象自定义格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import logging, sys
FMT = '%(asctime)s %(levelname) 8s: [%(filename)s:%(lineno)d] [%(processName)s:%(process)d %(threadName)s] - %(message)s'
DATEFMT = '[%Y-%m-%d %H:%M:%S]'
logger_handler = logging.StreamHandler(sys.stdout)
logger_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter(fmt=FMT, datefmt=DATEFMT)
logger_handler.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(logger_handler)
|
关键代码是 9-10 行,初始化一个格式化器,并设置到 Handler 对象上。 初始化器需要两个参数, fmt 指定日志格式, datefmt 指定日期格式。 除了日志内容,日志记录可以注入 时间 、 级别 、 代码文件名 、 代码行数 、 进程名 、 进程ID 、 线程名 等信息。
例子输出大致如下,可以看到 格式更为美观,信息更为丰富 了:
>>> logger.info('Hello, world!')
[2019-01-08 11:25:50] INFO: [<stdin>:1] [MainProcess:99324 MainThread] - Hello, world!