Python3日志记录 - MemoryHandler和flushOnClose行为

时间:2017-06-13 09:13:46

标签: python-3.x logging

如果我忘记在脚本结束前关闭MemoryHandler,即使flushOnClose=False(Python 3.6)也会显示日志消息'debug'。

我做错了什么或这是预期的行为?无论句柄如何关闭(即脚本结束时),我都会认为flushOnClose会被遵守。

import logging.config

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# file handler, triggered by the memory handler
fh = logging.FileHandler('log.txt')
# set the logging level
fh.setLevel(logging.DEBUG)

# capacity is the number of records
mh = logging.handlers.MemoryHandler(5, flushLevel=logging.ERROR, target=fh, flushOnClose=False)

logger.addHandler(mh)

logger.debug('debug')

# mh.close()

对于参数5, flushLevel=logging.ERROR, target=fh, flushOnClose=False,不应显示“debug”消息,因为

  1. 我没有在队列中添加5条消息
  2. flushOnClose = False,因此当脚本结束时,不应该有一个刷新
  3. debug不会触发flushLevel
  4. 的刷新

    我发现当我使用mh.close()时,消息不会按预期刷新。但是,当脚本在没有mh.close()(注释)的情况下结束时,尽管设置建议它不应该刷新,但是单个调试消息似乎会被刷新。

2 个答案:

答案 0 :(得分:1)

我认为这是正确的行为:

logger.debug('debug') - >这将打印到您的文件'debug',而无需等待任何刷新。

抱歉......是的,默认为True。我看到上面的添加,在我看来行为是正常的,从某种意义上说,如果你不终止,那么在执行结束时一切都将是齐平的(这是典型的,以便调试出错的地方)。如果你正在终止,那么消息被附加到缓冲区并且“False”导致消息在缓冲区内被销毁。这不是正确的行为吗?

此外,flushOnClose在处理程序类中不存在,如下所示:

class MemoryHandler(BufferingHandler):
    """
    A handler class which buffers logging records in memory, periodically
    flushing them to a target handler. Flushing occurs whenever the buffer
    is full, or when an event of a certain severity or greater is seen.
    """
    def __init__(self, capacity, flushLevel=logging.ERROR, target=None):
        """
        Initialize the handler with the buffer size, the level at which
        flushing should occur and an optional target.

        Note that without a target being set either here or via setTarget(),
        a MemoryHandler is no use to anyone!
        """
        BufferingHandler.__init__(self, capacity)
        self.flushLevel = flushLevel
        self.target = target

    def shouldFlush(self, record):
        """
        Check for buffer full or a record at the flushLevel or higher.
        """
        return (len(self.buffer) >= self.capacity) or \
                (record.levelno >= self.flushLevel)

    def setTarget(self, target):
        """
        Set the target handler for this handler.
        """
        self.target = target

    def flush(self):
        """
        For a MemoryHandler, flushing means just sending the buffered
        records to the target, if there is one. Override if you want
        different behaviour.

        The record buffer is also cleared by this operation.
        """
        self.acquire()
        try:
            if self.target:
                for record in self.buffer:
                    self.target.handle(record)
                self.buffer = []
        finally:
            self.release()

    def close(self):
        """
        Flush, set the target to None and lose the buffer.
        """
        try:
            self.flush()
        finally:
            self.acquire()
            try:
                self.target = None
                BufferingHandler.close(self)
            finally:
                self.release()

无论如何,这种行为是正常的,从某种意义上说,即使你打开一个文件,你现在也可以决定是否关闭。最后,文件将被关闭,以免丢失信息: - )

答案 1 :(得分:0)

也解决了这个问题,除非除非遇到<错误> 事件,否则记录程序不应打印任何内容。 必须通过close()在Logger实例的所有MemoryHandler上手动调用atexit

def _close_all_memory_handlers():
    for handler in Logger.handlers:
        if isinstance(handler, logging.handlers.MemoryHandler):
            handler.close()
import atexit
atexit.register(_close_all_memory_handlers)

只要初始化atexit模块后注册此logging处理程序,此方法就应该起作用。