• 日志(Logging)
    • … 或者打印?
    • 库中的日志
    • 应用程序中的日志
      • 通过INI文件进行配置的例子
      • 通过字典进行配置的例子
      • 通过源码直接配置的例子

    日志(Logging)

    https://farm5.staticflickr.com/4246/35254379756_c9fe23f843_k_d.jpg
    日志模块自2.3版本开始便是Python标准库的一部分。它被简洁的描述在 PEP 282。众所周知,除了 基础日志指南 部分,该文档并不容易阅读。

    日志的两个目的:

    • 诊断日志 记录与应用程序操作相关的日志。例如,用户遇到的报错信息,可通过搜索诊断日志获得上下文信息。
    • 审计日志 为商业分析而记录的日志。从审计日志中,可提取用户的交易信息,并结合其他用户资料构成用户报告或者用来优化商业目标。

    … 或者打印?

    当需要在命令行应用中显示帮助文档时, 打印 是一个相对于日志更好的选择。而在其他时候,日志总能优于 打印 ,理由如下:

    • 日志事件产生的 日志记录 ,包含清晰可用的诊断信息,如文件名称、路径、函数名和行号等。
    • 包含日志模块的应用,默认可通过根记录器对应用的日志流进行访问,除非您将日志过滤了。
    • 可通过 logging.Logger.setLevel() 方法有选择地记录日志,或可通过设置 logging.Logger.disabled 属性为 True 来禁用。

    库中的日志

    日志指南 中含 库日志配置 的说明。由于是 用户 ,而非库来指明如何响应日志事件,因此这里有一个值得反复说明的忠告:

    注解

    强烈建议不要向您的库日志中加入除NullHandler外的其它处理程序。

    在库中,声明日志的最佳方式是通过 name 全局变量: logging模块通过点(dot)运算符创建层级排列的日志,因此,用 name 可以避免名字冲突。

    以下是一个来自 requests 资源 的最佳实践的例子 —— 把它放置在您的 init.py 文件中

    1. import logging
    2. logging.getLogger(__name__).addHandler(logging.NullHandler())

    应用程序中的日志

    应用程序开发的权威指南, 应用的12要素 ,也在其中一节描述了日志的作用 。它特别强调将日志视为事件流,并将其发送至由应用环境所处理的标准输出中。

    配置日志至少有以下三种方式:

    • 使用INI格式文件:
      • 优点: 使用 logging.config.listen() 函数监听socket,可在运行过程中更新配置
      • 缺点: 通过源码控制日志配置较少( 例如 子类化定制的过滤器或记录器)。
    • 使用字典或JSON格式文件:
      • 优点: 除了可在运行时动态更新,在Python 2.6之后,还可通过 json模块从其它文件中导入配置。
      • 缺点: 很难通过源码控制日志配置。
    • 使用源码:
      • 优点: 对配置绝对的控制。
      • 缺点: 对配置的更改需要对源码进行修改。

    通过INI文件进行配置的例子

    我们假设文件名为 logging_config.ini 。关于文件格式的更多细节,请参见日志指南 中的 日志配置 部分。

    1. [loggers]
    2. keys=root
    3.  
    4. [handlers]
    5. keys=stream_handler
    6.  
    7. [formatters]
    8. keys=formatter
    9.  
    10. [logger_root]
    11. level=DEBUG
    12. handlers=stream_handler
    13.  
    14. [handler_stream_handler]
    15. class=StreamHandler
    16. level=DEBUG
    17. formatter=formatter
    18. args=(sys.stderr,)
    19.  
    20. [formatter_formatter]
    21. format=%(asctime)s %(name)-12s %(levelname)-8s %(message)s

    然后在源码中调用 logging.config.fileConfig() 方法:

    1. import logging
    2. from logging.config import fileConfig
    3.  
    4. fileConfig('logging_config.ini')
    5. logger = logging.getLogger()
    6. logger.debug('often makes a very good meal of %s', 'visiting tourists')

    通过字典进行配置的例子

    Python 2.7中,您可以使用字典实现详细配置。PEP 391 包含了一系列字典配置的强制和非强制的元素。

    1. import logging
    2. from logging.config import dictConfig
    3.  
    4. logging_config = dict(
    5. version = 1,
    6. formatters = {
    7. 'f': {'format':
    8. '%(asctime)s%(name)-12s%(levelname)-8s%(message)s'}
    9. },
    10. handlers = {
    11. 'h': {'class': 'logging.StreamHandler',
    12. 'formatter': 'f',
    13. 'level': logging.DEBUG}
    14. },
    15. root = {
    16. 'handlers': ['h'],
    17. 'level': logging.DEBUG,
    18. },
    19. )
    20.  
    21. dictConfig(logging_config)
    22.  
    23. logger = logging.getLogger()
    24. logger.debug('often makes a very good meal of %s', 'visiting tourists')

    通过源码直接配置的例子

    1. import logging
    2.  
    3. logger = logging.getLogger()
    4. handler = logging.StreamHandler()
    5. formatter = logging.Formatter(
    6. '%(asctime)s%(name)-12s%(levelname)-8s%(message)s')
    7. handler.setFormatter(formatter)
    8. logger.addHandler(handler)
    9. logger.setLevel(logging.DEBUG)
    10.  
    11. logger.debug('often makes a very good meal of %s', 'visiting tourists')

    原文: http://pythonguidecn.readthedocs.io/zh/latest/writing/logging.html