【问题标题】:Python logging: Create new log file if it is deleted while program is running (RotatingFileHandler)Python日志记录:如果在程序运行时删除它,则创建新的日志文件(RotatingFileHandler)
【发布时间】:2017-04-24 15:23:44
【问题描述】:

我有一个 python 程序正在运行,它使用 TimedRotatingFileHandler 连续记录到一个文件。有时我希望在关闭程序的情况下获取日志文件,因此我只需将日志文件剪切并粘贴到其他位置即可。

如果我这样做,程序不会崩溃,但也不会再登录到任何文件。

看了BaseRotatingFileHandler的源码后:

def emit(self, record):
    try:
        if self.shouldRollover(record):
            self.doRollover()
        logging.FileHandler.emit(self, record)
    except Exception:
        self.handleError(record)

我想我可以继承 TimedRotatingFileHandler 并像这样重新实现它的发出函数:

def emit(self, record):
    try:
        if not os.path.exists(self.baseFilename) or self.shouldRollover(record):
            self.doRollover()
        logging.FileHandler.emit(self, record)
    except Exception:
        self.handleError(record)

下面的 sn-p 似乎达到了我想要的效果。但我不确定我的方法是否是解决问题的最佳方法。有没有更好的方法来实现这一点,或者我做得对吗?

import logging.handlers
import logging
import time
import os


class TimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):
    def __init__(self, filename, **kwargs):
        super().__init__(filename, **kwargs)

    def emit(self, record):
        try:
            if not os.path.exists(self.baseFilename) or self.shouldRollover(record):
                self.doRollover()
            logging.FileHandler.emit(self, record)
        except Exception:
            self.handleError(record)


logging.basicConfig(handlers = [TimedRotatingFileHandler('test.log')])

for x in range(10):
    time.sleep(1)
    logging.critical('test')

编辑:

我应用了@danny 提供的解决方案。为了保持 RotatingFileHandler 的能力,我创建了一个 TimedRotatingFileHandler 和 WatchedFileHandler 的混合类:

class WatchedTimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler, logging.handlers.WatchedFileHandler):
    def __init__(self, filename, **kwargs):
        super().__init__(filename, **kwargs)
        self.dev, self.ino = -1, -1
        self._statstream()

    def emit(self, record):
        self.reopenIfNeeded()
        super().emit(record)

【问题讨论】:

  • 改变一个被其他进程打开的文件的影响取决于操作系统、文件系统、打开模式和其他一些东西。
  • 正如 danny 在 linux 上正确总结的那样
  • 我注意到 WatchedFileHandler 的构造函数从未被调用...所以您将这些代码行复制到您的构造函数中...非常聪明。此代码的行为是否符合您的预期/想要/需要?
  • 没错。是的,它当时有效。但不保证将来(或现在?)可以工作
  • @johnson 你能解释一下 self.dev, self.ino = -1, -1 & self._statstream() & reOpenIfNeeded 吗?或者你能指导我一些资源吗?

标签: python python-3.x logging


【解决方案1】:

由于在 Windows 平台上无法更改打开的文件,可以肯定地说 OP 不是在寻找跨平台解决方案。

在这种情况下,logging.handlers.WatchedFileHandler 是在记录到的文件更改时继续记录的适当解决方案。

来自文档:

WatchedFileHandler 类,位于 logging.handlers 模块中, 是一个 FileHandler,它监视它正在记录的文件。如果文件 更改后,它会关闭并使用文件名重新打开。

没有可用的旋转监视文件处理程序,因此必须使用此解决方案将旋转移动到logrotate 或类似位置。

或者使用TimedRotatingHandler 的补丁,除了您已经拥有的代码之外,还需要正确关闭并重新打开文件句柄,以匹配WatchedFileHandler 所做的事情。

【讨论】:

    【解决方案2】:

    处理它的最跨平台方法是只获取“旧”文件,而将最新文件保留在原处。 即使不更改处理程序实现,这也可以工作,并且在不同平台下不会失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-31
      相关资源
      最近更新 更多