Python 日志记录 - 关闭多个日志中的一个文件(ResourceWarning)

时间:2021-03-24 15:42:37

标签: python python-3.x logging file-io python-logging

我创建了一个自定义 logging.Logger,在我正在运行的脚本中由多个不同对象使用:

class TestLogger(logging.Logger):
    def __init__(self, name, file=None):
        super(TestLogger, self).__init__(name, level=logging.DEBUG)
        self.log_file = file
        ...

    def addLogFile(self, log_file):
        self.log_file = log_file
        self.setFormat()

    # set the format of the log
    def setFormat(self, default=True, end='\n'):

        # remove any Handlers
        self.removeStreamHandlers()
        self.removeFileHandlers()

        # get the log format string, default or message
        format_str = DEFAULT_FORMAT if default else CUSTOM_FORMAT

        std_formatter = logging.Formatter(format_str, datefmt=self.DATE_FORMAT)

        # add the stream handler
        console = logging.StreamHandler(sys.stdout)
        console.setFormatter(std_formatter)
        console.terminator = end
        self.addHandler(console)

        # add the file handler
        if self.log_file:
            file_formatter = logging.Formatter(format_str, datefmt=self.DATE_FORMAT)
            logger = logging.FileHandler(self.log_file)
            logger.setFormatter(file_formatter)
            self.addHandler(logger)

    # remove all stream handlers
    def removeStreamHandlers(self):
        stream_handlers = [h for h in self.handlers if isinstance(h, logging.StreamHandler)
                           and not isinstance(h, logging.FileHandler)]
        for sh in stream_handlers:
            self.removeHandler(sh)

    # remove all file handlers
    def removeFileHandlers(self):
        file_handlers = [h for h in self.handlers if isinstance(h, logging.StreamHandler)
                         and isinstance(h, logging.FileHandler)]
        for fh in file_handlers:
            self.removeHandler(fh)

class Something:
    def __init__(self):
        self.log = TestLogger('Something')
        ...
    def __del__(self):
        self.log.removeFileHandlers()
        self.log.removeStreamHandler()

class SomethingElse:
    def __init__(self):
        self.log = TestLogger('SomethingElse')
        ...
    def __del__(self):
        self.log.removeFileHandlers()
        self.log.removeStreamHandler()

所有这些对象都被初始化并设计为共享相同的日志文件,如下所示:

log_file = 'test.log'
s = Something()
se = SomethingElse()
s.addLogFile(log_file)
se.addLogFile(log_file)
...
del s, se

问题似乎是,当我尝试重新运行我的程序时,每次运行 ResourceWarning 时它都会抛出一个 setFormat()。该文件似乎没有正确关闭,我不确定这可能发生在哪里。

1 个答案:

答案 0 :(得分:0)

首先,您应该重用处理程序。如果您想更改格式化程序,只需在现有处理程序上调用 setFormatter 并保留它们。

如果您真的想丢弃处理程序并使用新的处理程序,FileHandler 上有一个 close() 方法,应该在处理程序完成日志记录后调用该方法进行清理。因此,在您的情况下,您可以将代码更改为如下所示:

        for fh in file_handlers:
            fh.close()
            self.removeHandler(fh)