【发布时间】:2014-04-02 10:04:08
【问题描述】:
当使用 python 中的 logging 模块进行日志记录时。为每个类定义一个记录器是最佳实践吗?
考虑到某些事情会是多余的,例如文件日志位置,我正在考虑将日志记录抽象到它自己的类中,并将一个实例导入到我的每个需要日志记录的类中。但是我不确定这是否是最佳做法?
【问题讨论】:
当使用 python 中的 logging 模块进行日志记录时。为每个类定义一个记录器是最佳实践吗?
考虑到某些事情会是多余的,例如文件日志位置,我正在考虑将日志记录抽象到它自己的类中,并将一个实例导入到我的每个需要日志记录的类中。但是我不确定这是否是最佳做法?
【问题讨论】:
最佳实践是遵循 Python 的软件(分解)组合规则 - 模块是 Python 软件的单元,而不是类。因此,推荐的方法是使用
logger = logging.getLogger(__name__)
在每个模块中,并从主脚本配置日志记录(使用basicConfig() 或dictConfig())。
记录器是单例的 - 传递它们或将它们存储在类的实例中是没有意义的。
【讨论】:
logger = logging.getLogger(__name__) 是在模块顶部还是在要记录的每个函数/方法内部?
import 语句之后)
使用 JSON 或 YAML 日志配置 - 在 Python 2.7 之后,您可以从 dict 加载日志配置。这意味着您可以从 JSON 或 YAML 文件加载日志记录配置。
Yaml 示例 -
version: 1
disable_existing_loggers: False
formatters:
simple:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
info_file_handler:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: simple
filename: info.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8
error_file_handler:
class: logging.handlers.RotatingFileHandler
level: ERROR
formatter: simple
filename: errors.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8
loggers:
my_module:
level: ERROR
handlers: [console]
propagate: no
root:
level: INFO
handlers: [console, info_file_handler, error_file_handler]
【讨论】:
使用结构化日志记录。两个很好的工具:
大多数日志记录系统都会告诉您应用程序中发生了什么, 而 eliot 也会告诉你它发生的原因。
eliot 是一个 Python 日志系统,它输出 动作:动作可以产生其他动作,最终它们要么 成功或失败。生成的日志告诉你你的故事 软件做了什么:发生了什么,是什么原因造成的。
结构化日志记录意味着您不会编写难以解析和 日志中难以保持一致的散文,但您记录事件 而是在上下文中发生。
我与艾略特有过非常积极的经历。
【讨论】: