如何:针对多个进程实例和文件的Python TimedRotatingFileHandle?
我刚被我的新合同弄得筋疲力尽。当前系统使用python日志模块进行定时日志文件旋转。问题在于,作为守护进程运行的进程的日志文件会正确旋转,而在完成时创建和销毁的进程实例的其他日志文件不会旋转。曾经我现在必须找到解决这个问题的办法。在互联网和python文档上研究了两天之后,我才走出了黑暗的一半。因为我是日志模块的新手,所以我看不到问题的答案,因为我可能是闭着眼睛看的 该过程从以下内容开始:如何:针对多个进程实例和文件的Python TimedRotatingFileHandle?,python,logging,rotation,Python,Logging,Rotation,我刚被我的新合同弄得筋疲力尽。当前系统使用python日志模块进行定时日志文件旋转。问题在于,作为守护进程运行的进程的日志文件会正确旋转,而在完成时创建和销毁的进程实例的其他日志文件不会旋转。曾经我现在必须找到解决这个问题的办法。在互联网和python文档上研究了两天之后,我才走出了黑暗的一半。因为我是日志模块的新手,所以我看不到问题的答案,因为我可能是闭着眼睛看的 该过程从以下内容开始: python /admin/bin/fmlog.py -l 10 -f /tmp/fmlog/fmapp_
python /admin/bin/fmlog.py -l 10 -f /tmp/fmlog/fmapp_log.log -d
其中:
-l 10 => DEBUG logging-level
-f ... => Filename to log to for app-instance
-d => run as daemon
下面显示了我的代码经过大量编辑的版本:
#!/usr/bin python
from comp.app import app, yamlapp
...
from comp.utils.log4_new import *
# Exceptions handling class
class fmlogException(compException): pass
class fmlog(app):
# Fmlog application class
def __init__(self, key, config, **kwargs):
# Initialise the required variables
app.__init__(self, key, config, **kwargs)
self._data = {'sid': self._id}
...
def process(self, tid=None):
if tid is not None:
self.logd("Using thread '%d'." % (tid), data=self._data)
# Run the fmlog process
self.logi("Processing this '%s'" % (filename), data=self._data)
...
def __doDone__(self, success='Failure', msg='', exception=None):
...
self.logd("Process done!")
if __name__ == '__main__':
def main():
with yamlapp(filename=config, cls=fmlog, configcls=fmlogcfg, sections=sections, loglevel=loglevel, \
logfile=logfile, excludekey='_dontrun', sortkey='_priority', usethreads=threads, maxthreads=max, \
daemon=daemon, sleep=sleep) as a:
a.run()
main()
YAMLAP进程(应用程序的子类)被实例化并作为守护进程运行,直到手动停止。此进程将仅创建一个或多个fmlog类实例,并在需要时(满足某些条件)调用process()函数。如果YAMLAP进程在线程模式下运行,则每个线程最多可以创建x个实例
应用程序进程代码:
#!/usr/bin/env python
...
from comp.utils.log4_new import *
class app(comp.base.comp, logconfig, log):
def __init__(self, cls, **kwargs):
self.__setdefault__('_configcls', configitem)
self.__setdefault__('_daemon', True)
self.__setdefault__('_maxthreads', 5)
self.__setdefault__('_usethreads', False)
...
comp.base.comp.__init__(self, **kwargs)
logconfig.__init__(self, prog(), **getlogkwargs(**kwargs))
log.__init__(self, logid=prog())
def __enter__(self):
self.logi(msg="Starting application '%s:%s' '%d'..." % (self._cls.__name__, \
self.__class__.__name__, os.getpid()))
return self
def ...
def run(self):
...
if self._usethreads:
...
while True:
self.logd(msg="Start of run iteration...")
if not self._usethreads:
while not self._q.empty():
item = self._q.get()
try:
item.process()
self.logd(msg="End of run iteration...")
time.sleep(self._sleep)
日志配置和设置通过log4_new.py类完成:
#!/usr/bin/env python
import logging
import logging.handlers
import re
class logconfig(comp):
def __init__(self, logid, **kwargs):
comp.__init__(self, **kwargs)
self.__setdefault__('_logcount', 20)
self.__setdefault__('_logdtformat', None)
self.__setdefault__('_loglevel', DEBUG)
self.__setdefault__('_logfile', None)
self.__setdefault__('_logformat', '[%(asctime)-15s][%(levelname)5s] %(message)s')
self.__setdefault__('_loginterval', 'S')
self.__setdefault__('_logintervalnum', 30)
self.__setdefault__('_logsuffix', '%Y%m%d%H%M%S')
self._logid = logid
self.__loginit__()
def __loginit__(self):
format = logging.Formatter(self._logformat, self._logdtformat)
if self._logfile:
hnd = logging.handlers.TimedRotatingFileHandler(self._logfile, when=self._loginterval, interval=self._logintervalnum, backupCount=self._logcount)
hnd.suffix = self._logsuffix
hnd.extMatch = re.compile(strftoregex(self._logsuffix))
else:
hnd = logging.StreamHandler()
hnd.setFormatter(format)
l = logging.getLogger(self._logid)
for h in l.handlers:
l.removeHandler(h)
l.setLevel(self._loglevel)
l.addHandler(hnd)
class log():
def __init__(self, logid):
self._logid = logid
def __log__(self, msg, level=DEBUG, data=None):
l = logging.getLogger(self._logid)
l.log(level, msg, extra=data)
def logd(self, msg, **kwargs):
self.__log__(level=DEBUG, msg=msg, **kwargs)
def ...
def logf(self, msg, **kwargs):
self.__log__(level=FATAL, msg=msg, **kwargs)
def getlogkwargs(**kwargs):
logdict = {}
for key, value in kwargs.iteritems():
if key.startswith('log'): logdict[key] = value
return logdict
日志记录按预期完成:来自yamlapp(应用程序的子类)的日志写入fmapp_log.log,来自fmlog的日志写入fmlog.log。
问题是fmapp_log.log按预期旋转,但fmlog.log从未旋转。我如何解决这个问题?我知道这个过程必须连续运行才能发生旋转,这就是为什么只使用一个记录器的原因。我怀疑必须为fmlog进程创建另一个句柄,该句柄在进程退出时决不能被销毁
要求:
应用程序(框架或主)日志和fmlog(流程)日志必须存储在不同的文件中。
两个日志文件都必须进行时间轮换
希望有人能理解上述内容,并能给我一些建议。我找到了一个解决方案:当子进程被破坏时,我不再删除处理程序。相反,如果处理程序已经存在,我只需重新使用它。我现在有两个主要的记录器,每个记录器都有一个处理器。1个用于主流程,1个在子模块运行时重复使用。仅当具有句柄的新记录器是以前未启动过的新子进程时,才会实例化该记录器。我还调整了代码,以便在为新子进程创建新句柄或重新启动主进程时滚动任何现有模块特定的日志文件。这样,日志文件会旋转,例如在午夜,即使主进程在午夜之前停止,并在午夜之后重新启动。也适用于子进程在午夜前运行,然后仅在午夜后某个时间再次运行的情况。它也适用于任何其他间隔设置。