【发布时间】: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