问题 重新定义日志记录根记录器


在我目前的项目中,有数千个代码行,如下所示:

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

我不想改变所有这些行,但我会改变日志行为。我的想法是将root logger更改为其他 Experimental logger,由ini-file配置:

[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问题,但我没有找到答案。


2717
2017-09-15 09:08


起源

第一。这有用吗?你有实际问题吗?第二。定义“更方便”两行代码似乎非常方便。你能想象多么方便? - S.Lott
有用!但我怀疑,这看起来像个黑客。 “更方便”意味着:“使用记录模块的一些标准功能”。抱歉。 - Aliaksei Ramanau
好人!格式化非常棒。 - Jakob Bowyer
“使用记录模块的一些标准功能”?您 是 使用日志记录模块的标准功能。您还可以使用哪些标准功能?你是否希望包中有这种确切配置的无证副本? - S.Lott
如果您只想从硬编码的“root”重命名根记录器,则可以设置无证件 name 属性: logging.root.name = 'myapp' 要么 logging.getLogger().name = 'myapp' - mykhal


答案:


你被告知  以您描述的方式重新定义根记录器。通常,您应该只将根记录器直接用于小脚本 - 对于大型应用程序,最佳实践是使用

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的一部分),并且在日志记录机器中还有其它对它的引用,它仍将指向旧值。这些事实中的任何一个都可能导致难以调试的问题。由于日志包允许多种方式来实现您想要的内容(貌似,记录到文件而不是控制台),因此您应该使用已提供的那些机制。


12
2017-09-15 12:04



“你被告知......”在哪里?这引起的问题是什么?答案的其余部分“一般......”非常好。但是,第一句话将受益于一些支持证据或文件。 - S.Lott
logging.root 是班上的 logging.RootLogger不是 logging.Logger。这些类的行为大多相同,但在某些情况下您可能会遇到不同的行为。某些类型的检查员也可能会发出警告。 - DarksteelPenguin


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

logger = logging.getLogger('name')  给你另一个记录器。


1
2018-02-02 12:02