13.11 给简单脚本增加日志功能

问题

你希望在脚本和程序中将诊断信息写入日志文件。

解决方案

打印日志最简单方式是使用 logging 模块。例如:

  1. import logging
  2.  
  3. def main():
  4. # Configure the logging system
  5. logging.basicConfig(
  6. filename='app.log',
  7. level=logging.ERROR
  8. )
  9.  
  10. # Variables (to make the calls that follow work)
  11. hostname = 'www.python.org'
  12. item = 'spam'
  13. filename = 'data.csv'
  14. mode = 'r'
  15.  
  16. # Example logging calls (insert into your program)
  17. logging.critical('Host %s unknown', hostname)
  18. logging.error("Couldn't find %r", item)
  19. logging.warning('Feature is deprecated')
  20. logging.info('Opening file %r, mode=%r', filename, mode)
  21. logging.debug('Got here')
  22.  
  23. if __name__ == '__main__':
  24. main()

上面五个日志调用(critical(), error(), warning(), info(), debug())以降序方式表示不同的严重级别。basicConfig()level 参数是一个过滤器。所有级别低于此级别的日志消息都会被忽略掉。每个logging操作的参数是一个消息字符串,后面再跟一个或多个参数。构造最终的日志消息的时候我们使用了%操作符来格式化消息字符串。

运行这个程序后,在文件 app.log 中的内容应该是下面这样:

  1. CRITICAL:root:Host www.python.org unknown
  2. ERROR:root:Could not find 'spam'

如果你想改变输出等级,你可以修改 basicConfig() 调用中的参数。例如:

  1. logging.basicConfig(
  2. filename='app.log',
  3. level=logging.WARNING,
  4. format='%(levelname)s:%(asctime)s:%(message)s')

最后输出变成如下:

  1. CRITICAL:2012-11-20 12:27:13,595:Host www.python.org unknown
  2. ERROR:2012-11-20 12:27:13,595:Could not find 'spam'
  3. WARNING:2012-11-20 12:27:13,595:Feature is deprecated

上面的日志配置都是硬编码到程序中的。如果你想使用配置文件,可以像下面这样修改 basicConfig() 调用:

  1. import logging
  2. import logging.config
  3.  
  4. def main():
  5. # Configure the logging system
  6. logging.config.fileConfig('logconfig.ini')
  7. ...

创建一个下面这样的文件,名字叫 logconfig.ini

  1. [loggers]
  2. keys=root
  3.  
  4. [handlers]
  5. keys=defaultHandler
  6.  
  7. [formatters]
  8. keys=defaultFormatter
  9.  
  10. [logger_root]
  11. level=INFO
  12. handlers=defaultHandler
  13. qualname=root
  14.  
  15. [handler_defaultHandler]
  16. class=FileHandler
  17. formatter=defaultFormatter
  18. args=('app.log', 'a')
  19.  
  20. [formatter_defaultFormatter]
  21. format=%(levelname)s:%(name)s:%(message)s

如果你想修改配置,可以直接编辑文件logconfig.ini即可。

讨论

尽管对于 logging 模块而已有很多更高级的配置选项,不过这里的方案对于简单的程序和脚本已经足够了。只想在调用日志操作前先执行下basicConfig()函数方法,你的程序就能产生日志输出了。

如果你想要你的日志消息写到标准错误中,而不是日志文件中,调用 basicConfig() 时不传文件名参数即可。例如:

  1. logging.basicConfig(level=logging.INFO)

basicConfig() 在程序中只能被执行一次。如果你稍后想改变日志配置,就需要先获取 root logger ,然后直接修改它。例如:

  1. logging.getLogger().level = logging.DEBUG

需要强调的是本节只是演示了 logging 模块的一些基本用法。它可以做更多更高级的定制。关于日志定制化一个很好的资源是 Logging Cookbook

原文:

http://python3-cookbook.readthedocs.io/zh_CN/latest/c13/p11_add_logging_to_simple_scripts.html