Python包中应如何使用日志记录?

33

我目前正在开发一个包,可以在不编写任何新代码的情况下使用它,并且这些模块可以用于开发新代码(参见文档)。

我的许多模块都以非常简单的方式使用logging

import logging
import sys
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
                    level=logging.DEBUG,
                    stream=sys.stdout)
# Code of the module follows

我在许多模块中都有这些行。我觉得我应该将其分解,但不确定最佳/推荐/最pythonic的方法是什么。

日志记录文档中相关部分似乎为 Configuring Logging for a LibraryLogging from multiple modules

我猜我应该将行logging.basicConfig移动到可执行文件 (bin/hwrt)中,并删除所有其他logging.basicConfig行。

是否有规则说明包应如何使用日志记录(类似于PEP8对编码风格的规定)?

如果其他开发人员使用我的代码,则可能希望禁用/修改我的软件包进行日志记录的方式(以使其不与他们的日志记录调用混合)。有办法帮助他们这样做吗?


依我之见,这个问题在这篇stackoverflow帖子中有较好的解释。 - Siete
1个回答

51

您的库不应配置日志记录; 这是一个应用程序范围的任务。

相反,只需基于 __name__ 设置您的记录器对象,然后使用它即可。文档中说明您使用了 logging ,使用您的库的开发人员可以使用标准的 logging API 配置日志记录。

您可以向根记录器 (为您的包名称注册的记录器) 添加空处理器,以防止在应用程序未设置默认配置时使用默认配置:

# This goes into your library somewhere
logging.getLogger('name.of.library').addHandler(logging.NullHandler())

使用您的库的开发人员可以通过禁用日志传播来仅针对您的库禁用所有日志记录:

logging.getLogger('name.of.library').propagate = False

这一切都已经在logging模块中有所记录;您可以将其视为Python日志的样式指南。从您已经链接到的“配置用于库的记录”部分中:

注意:强烈建议您不要向库的记录器添加任何处理程序,除了NullHandler之外。这是因为处理程序的配置是使用您的库的应用程序开发人员的专属权利。应用程序开发人员了解他们的目标受众以及最适合他们的应用程序的处理程序:如果您在“幕后”添加处理程序,则可能会干扰他们执行单元测试并生成符合他们要求的日志。

logging.basicConfig()正是如此;它创建处理程序配置。


1
logging.basicConfig()” 就是这样,它创建处理程序配置。只是为了确保:这意味着我不应该在我的库代码中使用 logging.basicConfig(),但在“可执行”部分中我可以使用它,对吗? - Martin Thoma
1
@moose:是的,绝对没错。你的“可执行”部分就是一个应用程序。模块中的__name__全局变量是模块名称,包括父级包。logging基于.分隔符创建日志对象层次结构,因此在foo.bar中的记录器会向上传播到foo;通过在库中的每个模块中使用logger = logging.getLogger(__name__),可以使自己更容易处理这方面的问题。 - Martijn Pieters
1
@变量 最后但并非最不重要的是:在您的库中使用 nullhandler 也可以防止在根记录器未配置时从您的库传递到 stderr 回退的日志消息。这就是使用它的全部目的。 - Martijn Pieters
4
如果你正在构建一个库,不要创建日志配置。在使用该库的应用程序中设置配置。你可以参考urllib3的做法,他们遵循了文档中关于库的最佳实践并且设置了一个空处理器。他们还提供了一种帮助调试的工具 - Martijn Pieters
3
@pyeR_biz:将其与MusicBrainz Picard等典型应用程序进行比较,该应用程序配置日志记录 - Martijn Pieters
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接