logger_problems
logger
的一些问题
logging
基础知识
在需要调试复杂情况的时候,我们都会使用 logging
而不是 print
,一般来说配置日志文件有两种方式,全局的 logger
或者局部的 logger
,全局的 logger
可以这样配置:
1 |
|
实际上这种方法虽然没有显示配置 logger
,但是其实是默认配置了 logger.root
logger
的配置方式一般为:
1 |
|
logging
可决定输出到什么地方,以及输出格式。有许多的重要性别级可供选择,debug、info、warning、error
以及critical
。通过赋予logger
或者handler
不同的级别,你就可以只输出错误消息到特定的记录文件中,或者在调试时只记录调试信息- 创建
logger
的过程中,getLogger
函数返回的logger
只与日志名称有关,输入相同的名称会返回同一个实例(如果是全局的logging
,那么logger
的名字就是root
) FileHandler
配置的参数和logging.basicConfig
对应,他们可以配置几乎完全相同的参数,例如输出格式,输出等级(配置输出格式使用setFormatter
方法)logger
可配置的参数只有level
,其他的参数全部是属于Handeler
配置
- 同一个
logger
可以加入多个Handler
,同一个Handler
也可以给多个logger
(这一点和 Java 相同)
logging msg
输出格式中可以配置的参数有:
1 |
|
暗箱操作导致多重日志
logging
的暗箱操作:logger
在没有 handler
的情况下,其本身是不具备输出消息能力的。但是为什么上面全局 logger
的例子中 logging.warning(msg)
能够在不配置 handler
的情况下,输出日志呢?这其实是 logging 模块的保护机制,对于 warning 和 error 级别的消息,如果消息的日志等级大于 logger
的日志等级,且 logger
没有配置任何的 handler
,则会调用 logging 模块内置的 streamHandler
来输出信息
坑爹的 logging.warning
当我们开心地调用 logging.warning
时,我们以为只是输出了一条日志,实际上可能给 logging.root
偷偷配置了 streamHandler
1 |
|
如果单纯的以为就多了个 streamHandler
就错了。他会引起多重日志的问题。为什么使用 pytorch 1.10 突然出现了多重日志?追根溯源,是因为 pytorch 1.10 的 DistributedDataParallel
模块在 forward
过程中调用了 logging.info ,进而 logging.root
多出了一个 streamHandler
,如果这个调用发生在 logging.getLogger
之后,就会导致多重日志的发生
- 为了避免多重日志的发生,我们最好配置输出的 formatter,让 logger 输出的日志自带 logger 名,这样就知道每条日志信息是哪一个
logger
产生,就很好调试了
万恶的logging.root
众所可能不周知, logging
库为了简化配置 logger
的流程,允许我们通过派生“子实例”来获取日志格式和父实例一样的 logger
。所有通过 logging.getLogger
方法创建的实例,都拥有共同的祖先:logging.root
1 |
|
子实例会继承父实例的属性,但是我们前面提到了 logger
的可配置参数只有 level
,这个东西继承并不会带来多重日志的问题,但是 logger
还有通过 propagate 属性继承(严格来说这不算继承) Handler
的机制,当 propagate 为 True 时,子实例会向上搜索并调用父实例的 Handler 从而触发多重打印。我们只需要另 propagate 为 False,能走出万恶的继承循环了
我们举一个错误的代码例子:
1 |
|
这样的错误代码在同一个文件内可能哈哈还会因为两种使用方式不同而发现,但如果是导入包的时候出现了这个问题那 debug 的难度是要上天了
代码的修改也很简单,将 child_logger
的 propagate 属性设置成 False 就行了:
1 |
|
loguru
:更简单的日志写法
loguru
是一个 Python 的记录日志的第三方库,旨在简化和改进应用程序的日志记录过程。loguru
试图通过提供有用的功能来解决标准库 logging 中的一些痛点,例如更简单的 API、自动处理日志文件的轮转、压缩等(但是这个库发现记录信息有点慢了)
1 |
|