手动使用MemoryHandler和FileHandler设置Python日志记录

3

我找不到足够的文档来使其工作。我的非长时间运行进程在stderr上显示进度信息并使用stdout输出。我希望在进程退出时日志消息全部汇集在一起,并且还应将其记录到文件中。根据我所查找的文档,MemoryHandlerFileHandler是我需要的东西。但是当我像下面这样设置它时,既没有在文件中也没有退出时得到任何输出。任何帮助将不胜感激。

import logging, logging.handlers, atexit, sys

filename = 'mylogfile.txt'
logLevel = logging.DEBUG

formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
streamhandler = logging.StreamHandler(sys.stderr)
streamhandler.setLevel(logLevel)
streamhandler.setFormatter(formatter)
memoryhandler = logging.handlers.MemoryHandler(1024*100, logLevel, streamhandler)

filehandler = logging.FileHandler(filename)
filehandler.setLevel(logLevel)
filehandler.setFormatter(formatter)

logger = logging.getLogger()
logger.addHandler(memoryhandler)
logger.addHandler(filehandler)
def flush():
    memoryhandler.flush()
atexit.register(flush)
logger.debug("Logger has Initialized")
2个回答

6

Vinay Sajip 提供了最重要的缺失线索:日志记录器确实有自己的级别,我忘记设置 DEBUG 记录将永远不会被发出。然而还有一个问题,导致 MemoryHandler 在接收到记录后立即刷新:它自己的级别需要设置得更高,因为它并不是像我假设的那样低于截止级别,而是在或高于处理程序立即刷新其记录到目标之前。参见文档以供参考。以下代码已解决这些问题,并以更加自说明的方式编写,以便知道这种微妙之处。

import logging, logging.handlers, atexit, sys

filename = 'mylogfile.txt'
logLevel = logging.DEBUG

formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
streamhandler = logging.StreamHandler(sys.stderr)
streamhandler.setLevel(logLevel)
streamhandler.setFormatter(formatter)
memoryhandler = logging.handlers.MemoryHandler(
    capacity=1024*100,
    flushLevel=logging.ERROR,
    target=streamhandler
)

filehandler = logging.FileHandler(filename)
filehandler.setLevel(logLevel)
filehandler.setFormatter(formatter)
logger = logging.getLogger()
logger.setLevel(logLevel)
logger.addHandler(memoryhandler)
logger.addHandler(filehandler)
def flush():
    memoryhandler.flush()
atexit.register(flush)
logging.debug("Logger has Initialized")
sys.stderr.write("I'd like this printed on the console first\n")

标准错误输出:

I'd like this printed on the console first
2015-12-07 10:42:45,707 - DEBUG - Logger has Initialized

mylogfile.txt:

2015-12-07 10:42:45,707 - DEBUG - Logger has Initialized

1
在这种情况下,您不一定需要指定flushLevel,因为如果未指定,则默认值为logging.ERROR - Vinay Sajip
谢谢。在我看来,由于默认行为有点出乎意料,明确说明会更好,从自我文档的角度来看。 - Michel Müller
嗨,米歇尔,我有一些问题。为什么日志记录器在这里正在刷新?你只添加了一条记录,所以缓冲区仍然有更多的内存,对吧?另外,容量等于记录数,那么为什么你要输入字节容量?我的问题可能听起来不好,但我需要清楚明白,所以请回答。 - Saket Suraj
嘿@SaketSuraj。就我所记得的,这里的刷新只是由程序退出触发的(atexit.register(flush))。这回答了你的问题吗? 编辑:关于容量,文档在这里并不明确,但就我所记得的,它是以字节为单位指定的。 - Michel Müller

3

您需要在日志记录器和处理程序上指定一个级别。只有在检查了日志记录器的级别后,才会查看处理程序的级别。

更多信息请参见此处


谢谢@VinaySajip!如果您不介意的话,我也创建了一个更完整的答案来修复另一个问题,但是非常感谢您的帮助。 - Michel Müller

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