编写代码时, 常要跟踪下其运行过程, 记录日志是常用的方式. 较简单的就是print命令打印到终端, 或通过open函数写入文件. 但随着代码量的增加, 该方式不可控的弊端, 也凸显出来, 这也正是logging模块出现的背景.
对于logging模块, 简单来说直接import进来, 就可以用了.
In [1]: import logging
In [2]: logging.warning('Watch out!')
WARNING:root:Watch out!
In [3]: logging.info('I told you so')
In [4]:
In [4]:
第二个语句没有输出呢, 这需了解下日志等级的概念. logging模块默认的日志等级是WARNING, 大于该等级的日志才会输出, 细节如下.
Level | When it’s used |
---|---|
DEBUG | Detailed information, typically of interest only when diagnosing problems. |
INFO | Confirmation that things are working as expected. |
WARNING | An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected. |
ERROR | Due to a more serious problem, the software has not been able to perform some function. |
CRITICAL | A serious error, indicating that the program itself may be unable to continue running. |
借助basicConfig方法, 可对日志记录做些配置.
In [1]: import logging
In [2]: logging.basicConfig(filename='/tmp/example.log',level=logging.DEBUG)
In [3]: logging.debug('This message should go to the log file')
In [4]: logging.info('So should this')
In [5]: logging.warning('And this, too')
$ cat /tmp/example.log
DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too
在脚本中, 可按照下面的方式使用logging模块.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# myapp.py
import logging
import mylib
def main():
logging.basicConfig(filename='myapp.log', format='%(asctime)s - %(name)s - %(levelname)s - %(pathname)s - %(message)s', level=logging.INFO)
logging.info('Started')
mylib.do_something()
logging.info('Finished')
if __name__ == '__main__':
main()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# mylib.py
import logging
def do_something():
logging.info('Doing something')
$ python myapp.py
$ cat myapp.log
2018-01-19 17:00:14,821 - root - INFO - myapp.py - Started
2018-01-19 17:00:14,821 - root - INFO - /home/zz/stage/mylib.py - Doing something
2018-01-19 17:00:14,821 - root - INFO - myapp.py - Finished
简单了解了logging模块的使用, 接着看下其中几个重要的概念.
1. Logger 日志记录器, 暴露给应用程序直接使用的接口, 几个方法用于设置记录器.
Logger.setLevel() - 指定日志记录器处理的日志最低级别.
Logger.addHandler(), Logger.removeHandler() - 为日志记录器添加, 或移除处理器.
2. Handler 处理器, 将记录器获取的日志, 传送到其定义的目的地, 也有几个方法设置处理器.
setLevel() - 指定处理器处理的日志最低级别.
setFormatter() - 为处理器选择一个格式化器.
3. Formatter 格式化器, 指定日志的输出格式.
最开始说了logging模块的简单用法, 以及了解了上面的概念后, 看下开发较大应用时, 如何使用logging呢.
这主要介绍两种方式, 其一是, 将logging模块的配置直接写在应用代码中, 如下所示.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# simple_logging_module.py
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
2018-01-19 21:41:58,180 - simple_example - DEBUG - debug message
2018-01-19 21:41:58,180 - simple_example - INFO - info message
2018-01-19 21:41:58,180 - simple_example - WARNING - warn message
2018-01-19 21:41:58,180 - simple_example - ERROR - error message
2018-01-19 21:41:58,180 - simple_example - CRITICAL - critical message
其二, 配置信息写入文件中, 借助fileConfig方法加载该文件, 如下所示.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# simple_logging_config.py
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')
# 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=
$ python simple_logging_config.py
2018-01-19 21:53:46,216 - simpleExample - DEBUG - debug message
2018-01-19 21:53:46,216 - simpleExample - INFO - info message
2018-01-19 21:53:46,216 - simpleExample - WARNING - warn message
2018-01-19 21:53:46,216 - simpleExample - ERROR - error message
2018-01-19 21:53:46,216 - simpleExample - CRITICAL - critical message
最后简单说下, 如何总结一个模块, 可围绕下面三点进行说明.
1. 该模块解决的问题, 其它方法是如何做的.
2. 模块的使用, 以及核心概念(或定义).
3. 核心API的梳理.