重新定义日志根记录器

23

在我的当前项目中,有成千上万行的代码看起来像这样:

logging.info("bla-bla-bla")

我不想改变所有这些行,但我希望改变日志记录的行为。我的想法是将根记录器更改为其他实验性记录器,该记录器通过ini文件进行配置:

[loggers]
keys =  Experimental

[formatter_detailed]
format = %(asctime)s:%(name)s:%(levelname)s %(module)s:%(lineno)d:  %(message)s

[handler_logfile]
class = FileHandler
args = ('experimental.log', 'a')
formatter = detailed

[logger_Experimental]
level = DEBUG
qualname = Experimental
handlers = logfile
propagate = 0

现在通过以下代码设置新的根记录器:

logging.config.fileConfig(path_to_logger_config)
logging.root = logging.getLogger('Experimental')

重新定义根记录器是否安全?也许有更方便的方法吗?

我尝试使用谷歌并查看了stackoverflow上的问题,但我没有找到答案。


首先,这个有用吗?你真的有问题吗? 其次,你如何定义“更方便”?两行代码已经非常方便了,你还能想象出更加方便的方式吗? - S.Lott
它能工作!但我怀疑,这看起来像是一个黑客。 “更方便”意味着:“使用日志模块的某些标准功能”。抱歉。 - Aliaksei Ramanau
好的,伙计!格式化真棒。 - Jakob Bowyer
1
你正在使用日志模块的标准功能。还有什么更标准的功能可以使用?你希望在包中有这个精确配置的未记录文档吗? - S.Lott
如果您想将根记录器从硬编码的“root”重命名,可以设置未记录的“name”属性:logging.root.name = 'myapp'logging.getLogger().name = 'myapp' - mykhal
2个回答

26

根据建议,您不应按照您所描述的方式重新定义根日志记录器。通常情况下,您只应在小型脚本中直接使用根日志记录器,对于较大的应用程序,最佳实践是使用。

logger = logging.getLogger(__name__)
在每个模块中使用日志记录时,请调用logger.info()等函数。
如果您只想记录到文件中,为什么不直接向根记录器添加文件处理程序?您可以通过以下方式完成:
if __name__ == '__main__':
    logging.basicConfig(filename='experimental.log', filemode='w')
    main() # or whatever your main entry point is called

或者通过配置文件。

更新: 当我说“建议使用”时,我是指在这个答案中;-) 虽然你可能不会在你的场景中遇到任何问题,但覆盖一个未设计为可覆盖的模块属性并不是一个好的实践。例如,根记录器是另一个类的实例(不是公共API的一部分),日志机制中还有其他对其的引用,这些引用仍将指向旧值。这两个事实都可能导致难以调试的问题。由于logging包允许多种方法来实现你似乎想要的功能(似乎是将日志记录到文件而不是控制台),因此应该使用已提供的机制。


2
建议您...在哪里?这会引起什么问题?其余的答案“一般来说...”非常好。但是第一句话需要一些支持性证据或文档。 - S.Lott
logging.rootlogging.RootLogger 类的实例,而不是 logging.Logger。这两个类大多数情况下表现相同,但在某些情况下可能会遇到不同的行为。一些类型检查器也可能会发出警告。 - DarksteelPenguin
覆盖根日志记录非常有用。例如,当您希望第三方模块也按照您的结构化格式进行日志记录时,这将非常有帮助。 - undefined
@MKesper 你可以在不重新定义根记录器的情况下实现这一点 - 所有的日志输出都是由应用程序开发人员配置的处理程序完成的,而设计良好的库不应该自行进行任何日志输出。 - undefined
@VinaySajip 你说得对。如果需要的话最好遍历处理程序(考虑gunicorn / uvicorn)。 - undefined

5

logger = logging.getLogger() 将名称留空将返回根记录器。

logger = logging.getLogger('name') 提供了另一个记录器。


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