我想在我的项目中使用内存记录器。它跟踪最后 n 个日志记录。一个最小的示例主文件如下所示:
import sys
import logging
from logging import StreamHandler
from test_module import do_stuff
logger = logging.getLogger(__name__)
class MemoryHandler(StreamHandler):
def __init__(self, n_logs: int):
StreamHandler.__init__(self)
self.n_logs = n_logs
self.my_records = []
def emit(self, record):
self.my_records.append(self.format(record))
self.my_records = self.my_records[-self.n_logs:]
def to_string(self):
return '\n'.join(self.my_records)
if __name__ == '__main__':
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
mem_handler = MemoryHandler(n_logs=10)
logger.addHandler(mem_handler)
logger.info('hello')
do_stuff()
print(mem_handler.to_string())
Run Code Online (Sandbox Code Playgroud)
我从中导入的测试模块do_stuff如下所示:
import sys
import logging
from logging import StreamHandler
from test_module import do_stuff
logger = logging.getLogger(__name__)
class MemoryHandler(StreamHandler):
def __init__(self, n_logs: int):
StreamHandler.__init__(self)
self.n_logs = n_logs
self.my_records = []
def emit(self, record):
self.my_records.append(self.format(record))
self.my_records = self.my_records[-self.n_logs:]
def to_string(self):
return '\n'.join(self.my_records)
if __name__ == '__main__':
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
mem_handler = MemoryHandler(n_logs=10)
logger.addHandler(mem_handler)
logger.info('hello')
do_stuff()
print(mem_handler.to_string())
Run Code Online (Sandbox Code Playgroud)
当我运行 main 函数时,会出现两个日志语句。来自 main 的一个和来自 doing stuff 的一个,但内存记录器只收到“hello”而不是“doing stuff”:
INFO:__main__:hello
INFO:test_module:doing stuff
hello
Run Code Online (Sandbox Code Playgroud)
我认为这是因为 mem_handler 没有添加到 test_module 记录器中。我可以通过显式添加 mem_handler 来解决此问题:
logging.getLogger('test_module').addHandler(mem_handler)
Run Code Online (Sandbox Code Playgroud)
但一般来说,我不想列出所有模块并手动添加 mem_handler。如何将 mem_handler 添加到项目中的所有记录器?
Python 日志系统是联合的。这意味着存在类似于包结构的树状结构。此结构按记录器名称工作,级别由点分隔。
如果您使用模块__name__来获取记录器,它将相当于包的点名称。例如:
package.subpackage.module
Run Code Online (Sandbox Code Playgroud)
在此联合系统中,一条消息将向上发送到记录器结构(除非其中一个记录器显式配置为propagate=False)。
因此,添加处理程序的最佳方法是将其添加到结构顶部的根记录器,并确保下面的所有记录器都传播。
您可以获取根记录器logging.getLogger()(没有任何名称),然后根据需要添加处理程序或其他配置。