gpt4 book ai didi

python - 如何使用 python 的 TimedRotatingFileHandler 强制旋转名称?

转载 作者:太空狗 更新时间:2023-10-30 02:04:04 26 4
gpt4 key购买 nike

我正在尝试使用 TimedRotatingFileHandler将每日日志保存在单独的日志文件中。轮换完美地按预期工作,但我不喜欢它的工作方式是文件的命名。

如果我将日志文件设置为 my_log_file.log,这将是“今天的”日志文件,当它在午夜更改日期时,它将重命名为 my_log_file.log.2014-07-08 末尾没有 .log 扩展名,并且将为新的一天创建一个新的 my_log_file.log

我想要得到的是将旧文件重命名为 my_log_file.2014-07-08.log 甚至 my_log_file-2014-07-08.log ,主要是 .log 在最后,而不是在中间。另外,我希望“今天的”日志文件已经用今天的日期命名,就像旧的一样。

有什么办法吗?

我发现我可以个性化后缀:

handler.suffix = "%Y-%m-%d"

但我没有办法删除内部 .log 部分并强制当前日志文件添加后缀。

最佳答案

我创建了一个 ParallelTimedRotatingFileHandler 类,主要目的是允许多个进程并行写入一个日志文件。此类解决的并行进程问题是:

  • 当所有进程都试图同时复制或重命名同一个文件时,会出现错误。
  • 这个问题的解决方案正是您建议的命名约定。因此,对于您在处理程序中提供的文件名 Service,日志记录不会转到例如Service.log 但今天到 Service.2014-08-18.log 和明天 Service.2014-08-19.log
  • 另一种解决方案是以 a(追加)模式而不是 w 模式打开文件,以允许并行写入。
  • 删除备份文件也需要谨慎,因为多个并行进程同时删除相同的文件。
  • 此实现不考虑闰秒(这对 Unix 来说不是问题)。在其他操作系统中,翻转时刻可能仍然是 30/6/2008 23:59:60,所以日期没有改变,因此,我们采用与昨天相同的文件名。
  • 我知道标准的 Python 建议是 logging 模块不适用于并行进程,我应该使用 SocketHandler,但至少在我的环境中,这是可行的。

该代码只是标准 Python handlers.py 模块中代码的细微变化。当然,版权属于版权所有者。

代码如下:

import logging
import logging.handlers
import os
import time
import re

class ParallelTimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, postfix = ".log"):

self.origFileName = filename
self.when = when.upper()
self.interval = interval
self.backupCount = backupCount
self.utc = utc
self.postfix = postfix

if self.when == 'S':
self.interval = 1 # one second
self.suffix = "%Y-%m-%d_%H-%M-%S"
self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$"
elif self.when == 'M':
self.interval = 60 # one minute
self.suffix = "%Y-%m-%d_%H-%M"
self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}$"
elif self.when == 'H':
self.interval = 60 * 60 # one hour
self.suffix = "%Y-%m-%d_%H"
self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}$"
elif self.when == 'D' or self.when == 'MIDNIGHT':
self.interval = 60 * 60 * 24 # one day
self.suffix = "%Y-%m-%d"
self.extMatch = r"^\d{4}-\d{2}-\d{2}$"
elif self.when.startswith('W'):
self.interval = 60 * 60 * 24 * 7 # one week
if len(self.when) != 2:
raise ValueError("You must specify a day for weekly rollover from 0 to 6 (0 is Monday): %s" % self.when)
if self.when[1] < '0' or self.when[1] > '6':
raise ValueError("Invalid day specified for weekly rollover: %s" % self.when)
self.dayOfWeek = int(self.when[1])
self.suffix = "%Y-%m-%d"
self.extMatch = r"^\d{4}-\d{2}-\d{2}$"
else:
raise ValueError("Invalid rollover interval specified: %s" % self.when)

currenttime = int(time.time())
logging.handlers.BaseRotatingHandler.__init__(self, self.calculateFileName(currenttime), 'a', encoding, delay)

self.extMatch = re.compile(self.extMatch)
self.interval = self.interval * interval # multiply by units requested

self.rolloverAt = self.computeRollover(currenttime)

def calculateFileName(self, currenttime):
if self.utc:
timeTuple = time.gmtime(currenttime)
else:
timeTuple = time.localtime(currenttime)

return self.origFileName + "." + time.strftime(self.suffix, timeTuple) + self.postfix

def getFilesToDelete(self, newFileName):
dirName, fName = os.path.split(self.origFileName)
dName, newFileName = os.path.split(newFileName)

fileNames = os.listdir(dirName)
result = []
prefix = fName + "."
postfix = self.postfix
prelen = len(prefix)
postlen = len(postfix)
for fileName in fileNames:
if fileName[:prelen] == prefix and fileName[-postlen:] == postfix and len(fileName)-postlen > prelen and fileName != newFileName:
suffix = fileName[prelen:len(fileName)-postlen]
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

def doRollover(self):
if self.stream:
self.stream.close()
self.stream = None

currentTime = self.rolloverAt
newFileName = self.calculateFileName(currentTime)
newBaseFileName = os.path.abspath(newFileName)
self.baseFilename = newBaseFileName
self.mode = 'a'
self.stream = self._open()

if self.backupCount > 0:
for s in self.getFilesToDelete(newFileName):
try:
os.remove(s)
except:
pass

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:
dstNow = time.localtime(currentTime)[-1]
dstAtRollover = time.localtime(newRolloverAt)[-1]
if dstNow != dstAtRollover:
if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour
newRolloverAt = newRolloverAt - 3600
else: # DST bows out before next rollover, so we need to add an hour
newRolloverAt = newRolloverAt + 3600
self.rolloverAt = newRolloverAt

关于python - 如何使用 python 的 TimedRotatingFileHandler 强制旋转名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24649789/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com