- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我确实在日志记录方面遇到了一些困难。我想在一段时间后以及达到一定大小后滚动日志。
一段时间后翻转由 TimedRotatingFileHandler
完成,达到一定日志大小后翻转由 RotatingFileHandler
完成.
但是TimedRotatingFileHandler
没有属性maxBytes
并且RotatingFileHandler
不能在一定时间后旋转。我也尝试将两个处理程序添加到记录器,但结果是双倍的记录。
我错过了什么吗?
我还查看了 logging.handlers
的源代码。我尝试子类化 TimedRotatingFileHandler
并重写方法 shouldRollover()
以创建具有两者功能的类:
class EnhancedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=0, maxBytes=0):
""" This is just a combination of TimedRotatingFileHandler and RotatingFileHandler (adds maxBytes to TimedRotatingFileHandler) """
# super(self). #It's old style class, so super doesn't work.
logging.handlers.TimedRotatingFileHandler.__init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=0)
self.maxBytes=maxBytes
def shouldRollover(self, record):
"""
Determine if rollover should occur.
Basically, see if the supplied record would cause the file to exceed
the size limit we have.
we are also comparing times
"""
if self.stream is None: # delay was set...
self.stream = self._open()
if self.maxBytes > 0: # are we rolling over?
msg = "%s\n" % self.format(record)
self.stream.seek(0, 2) #due to non-posix-compliant Windows feature
if self.stream.tell() + len(msg) >= self.maxBytes:
return 1
t = int(time.time())
if t >= self.rolloverAt:
return 1
#print "No need to rollover: %d, %d" % (t, self.rolloverAt)
return 0
但是像这样,日志会创建一个备份并被覆盖。似乎我还必须重写方法 doRollover()
,这并不容易。
关于如何创建一个在特定时间后以及达到特定大小后滚动文件的记录器还有其他想法吗?
最佳答案
所以我对 TimedRotatingFileHandler
做了一个小改动,以便能够在时间和大小之后进行翻转。我必须修改 __init__
、shouldRollover
、doRollover
和 getFilesToDelete
(见下文)。这是结果,当我设置 when='M', interval=2, backupCount=20, maxBytes=1048576 时:
-rw-r--r-- 1 user group 185164 Jun 10 00:54 sumid.log
-rw-r--r-- 1 user group 1048462 Jun 10 00:48 sumid.log.2011-06-10_00-48.001
-rw-r--r-- 1 user group 1048464 Jun 10 00:48 sumid.log.2011-06-10_00-48.002
-rw-r--r-- 1 user group 1048533 Jun 10 00:49 sumid.log.2011-06-10_00-48.003
-rw-r--r-- 1 user group 1048544 Jun 10 00:50 sumid.log.2011-06-10_00-49.001
-rw-r--r-- 1 user group 574362 Jun 10 00:52 sumid.log.2011-06-10_00-50.001
您可以看到前四个日志在达到 1MB 大小后翻转,而最后一个翻转发生在两分钟后。到目前为止,我没有测试删除旧日志文件,所以它可能不起作用。该代码肯定不适用于 backupCount>=1000。我在文件名末尾仅附加了三位数字。
这是修改后的代码:
class EnhancedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=0, maxBytes=0):
""" This is just a combination of TimedRotatingFileHandler and RotatingFileHandler (adds maxBytes to TimedRotatingFileHandler) """
logging.handlers.TimedRotatingFileHandler.__init__(self, filename, when, interval, backupCount, encoding, delay, utc)
self.maxBytes=maxBytes
def shouldRollover(self, record):
"""
Determine if rollover should occur.
Basically, see if the supplied record would cause the file to exceed
the size limit we have.
we are also comparing times
"""
if self.stream is None: # delay was set...
self.stream = self._open()
if self.maxBytes > 0: # are we rolling over?
msg = "%s\n" % self.format(record)
self.stream.seek(0, 2) #due to non-posix-compliant Windows feature
if self.stream.tell() + len(msg) >= self.maxBytes:
return 1
t = int(time.time())
if t >= self.rolloverAt:
return 1
#print "No need to rollover: %d, %d" % (t, self.rolloverAt)
return 0
def doRollover(self):
"""
do a rollover; in this case, a date/time stamp is appended to the filename
when the rollover happens. However, you want the file to be named for the
start of the interval, not the current time. If there is a backup count,
then we have to get a list of matching filenames, sort them and remove
the one with the oldest suffix.
"""
if self.stream:
self.stream.close()
# get the time that this sequence started at and make it a TimeTuple
currentTime = int(time.time())
dstNow = time.localtime(currentTime)[-1]
t = self.rolloverAt - self.interval
if self.utc:
timeTuple = time.gmtime(t)
else:
timeTuple = time.localtime(t)
dstThen = timeTuple[-1]
if dstNow != dstThen:
if dstNow:
addend = 3600
else:
addend = -3600
timeTuple = time.localtime(t + addend)
dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple)
if self.backupCount > 0:
cnt=1
dfn2="%s.%03d"%(dfn,cnt)
while os.path.exists(dfn2):
dfn2="%s.%03d"%(dfn,cnt)
cnt+=1
os.rename(self.baseFilename, dfn2)
for s in self.getFilesToDelete():
os.remove(s)
else:
if os.path.exists(dfn):
os.remove(dfn)
os.rename(self.baseFilename, dfn)
#print "%s -> %s" % (self.baseFilename, dfn)
self.mode = 'w'
self.stream = self._open()
newRolloverAt = self.computeRollover(currentTime)
while newRolloverAt <= currentTime:
newRolloverAt = newRolloverAt + self.interval
#If DST changes and midnight or weekly rollover, adjust for this.
if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc:
dstAtRollover = time.localtime(newRolloverAt)[-1]
if dstNow != dstAtRollover:
if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour
addend = -3600
else: # DST bows out before next rollover, so we need to add an hour
addend = 3600
newRolloverAt += addend
self.rolloverAt = newRolloverAt
def getFilesToDelete(self):
"""
Determine the files to delete when rolling over.
More specific than the earlier method, which just used glob.glob().
"""
dirName, baseName = os.path.split(self.baseFilename)
fileNames = os.listdir(dirName)
result = []
prefix = baseName + "."
plen = len(prefix)
for fileName in fileNames:
if fileName[:plen] == prefix:
suffix = fileName[plen:-4]
if self.extMatch.match(suffix):
result.append(os.path.join(dirName, fileName))
result.sort()
if len(result) < self.backupCount:
result = []
else:
result = result[:len(result) - self.backupCount]
return result
关于python - logging.handlers : How to rollover after time or maxBytes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6167587/
我对 Django 的 RotatingFileHander 有疑问。 问题是当文件达到 maxBytes 大小时,它不会创建新文件,并在您尝试执行 logger.info("any message"
我确实在日志记录方面遇到了一些困难。我想在一段时间后以及达到一定大小后滚动日志。 一段时间后翻转由 TimedRotatingFileHandler 完成,达到一定日志大小后翻转由 RotatingF
我正在尝试对 logging 模块的 RotatingFileHandler 进行如下测试: from logging import getLogger, Formatter from logging
我正在使用以下代码来限制日志文件的大小(最小示例): import logging from logging.handlers import RotatingFileHandler # Set up
我是一名优秀的程序员,十分优秀!