简体   繁体   English

Windows下Python记录器`RotatingFileHandler`失败

[英]Python logger `RotatingFileHandler` failing under Windows

I am trying to use the RotatingFileHandler handler to manage potentially long logfiles for a Python project running under Windows. 我正在尝试使用RotatingFileHandler处理程序来管理Windows下运行的Python项目的可能很长的日志文件。 I have found that the log file rotation works fine when run using the IDLE interpreter (on a Windows PC) but fails with a WindowsError exception when run from the Windows command prompt. 我发现,使用IDLE解释器(在Windows PC上)运行时,日志文件旋转可以正常运行,但是从Windows命令提示符运行时,日志文件旋转会失败,并出现WindowsError异常。

Here is an example code that shows the problem - 这是显示问题的示例代码-

import logging, logging.handlers
import datetime
import time

mainlogfile = 'fred.log'
logging_level = logging.DEBUG
logging_rotate_time = datetime.timedelta(minutes=1)

logger = logging.getLogger('Main_Logger')
logger.setLevel(logging.DEBUG)

handler = logging.handlers.RotatingFileHandler(mainlogfile, backupCount=7)
handler.setLevel(logging_level)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)      
logger.addHandler(handler)

next_rotate = datetime.datetime.now() + logging_rotate_time

while True:
    time.sleep(5)
    logger.info('Tick ')
    n = datetime.datetime.now()
    if n>next_rotate:
        logger.info('Rotating logfile')
        handler.doRollover()
        logger.info('Succesfully rotated logfile')
        next_rotate = next_rotate + logging_rotate_time
        logger.info('Next logfile rotate at '+ str(next_rotate))

When I run this in the IDLE interpreter, it works fine and the log file fred.log is rotated every minute producing fred.log.1, fred.log.2 etc. with contents such as - 当我在IDLE解释器中运行此文件时,它工作正常,并且日志文件fred.log每分钟旋转一次,生成fred.log.1, fred.log.2等,其内容如下-

2018-12-10 12:24:40,269 INFO Succesfully rotated logfile
2018-12-10 12:24:40,269 INFO Next logfile rotate at 2018-12-10 12:25:40.182000
2018-12-10 12:24:45,269 INFO Tick 
2018-12-10 12:24:50,269 INFO Tick 
2018-12-10 12:24:55,269 INFO Tick 
2018-12-10 12:25:00,267 INFO Tick 
2018-12-10 12:25:05,267 INFO Tick 
2018-12-10 12:25:10,266 INFO Tick 
2018-12-10 12:25:15,266 INFO Tick 
2018-12-10 12:25:20,266 INFO Tick 
2018-12-10 12:25:25,266 INFO Tick 
2018-12-10 12:25:30,265 INFO Tick 
2018-12-10 12:25:35,265 INFO Tick 
2018-12-10 12:25:40,263 INFO Tick 
2018-12-10 12:25:40,263 INFO Rotating logfile

However, when run in a command prompt it fails on the first rotate attempt - 但是,在命令提示符下运行时,第一次尝试旋转失败-

C:\> python try10.py
Traceback (most recent call last):
  File "try10.py", line 29, in <module>
    handler.doRollover()
  File "C:\Python27\lib\logging\handlers.py", line 142, in doRollover
    os.rename(self.baseFilename, dfn)
WindowsError: [Error 32] The process cannot access the file because it is being used by another process

I have searched and found that there are problems under Windows when trying to close or rename log files that are in use by another Python process but I can't see how that is relevant to my simple example. 我已搜查,发现试图关闭或重命名由另一个Python过程中使用的日志文件时 Windows下的问题,但我看不出这是有关我的简单的例子。 I have tried calling handler.flush() and handler.close() before handler.doRollover() but this did not change the behavior. 我试过在handler.doRollover()之前调用handler.flush()handler.close() ,但这并没有改变行为。

My questions are - 我的问题是-

  • Why is the exception raised when run at the command prompt but not under IDLE? 为什么在命令提示符下而不是在IDLE下运行时引发异常?
  • Is there any changes I can make to the code to allow it to run at the Windows command prompt 我可以对代码进行任何更改,以使其在Windows命令提示符下运行吗?

Looking at the code of the doRollover() method in the logging.handlers module, it can be seen that the exception above is being raised when doRollover tries to rename the log-file fred.log to fred.log.1 using os.rename() . 综观的代码doRollover()中方法logging.handlers模块,它可以看出,上述被引发的异常时doRollover尝试重命名记录文件fred.logfred.log.1使用os.rename() Trying to rename an open file like this will cause the exception under Windows, although earlier in the doRollover() method the open logfile should have been closed. 尝试像这样重命名打开的文件将导致Windows下的异常,尽管在doRollover()方法的早期,打开的日志文件应已关闭。 Since my program as stands always fails in Windows console it looks like the logfile is not being properly closed. 由于我的程序在Windows控制台中总是失败,因此日志文件似乎没有正确关闭。 In the IDLE interpreter, it seems that file i/o is done differently than the console (via sockets as described in the documentation ) so maybe that this is what allows the code to run there. 在IDLE解释器中,似乎文件I / O的完成方式不同于控制台(通过文档所述的套接字),因此也许这是允许代码在此处运行的原因。

Given that in order to allow doRollover() to rename the logfile, it has to be closed first and I discovered that this can be forced by temporarily removing the handler from the logger while doing the rollover - like this - 鉴于为了允许doRollover()重命名日志文件,必须首先将其关闭,我发现可以通过在进行过渡时从记录器中临时删除处理程序来强制执行此操作-像这样-

while True:
    time.sleep(5)
    logger.info('Tick ')
    n = datetime.datetime.now()
    if n>next_rotate:
        logger.info('Rotating logfile')

        logger.removeHandler(handler)      
        handler.doRollover()        
        logger.addHandler(handler)

        logger.info('Succesfully rotated logfile')
        next_rotate = next_rotate + logging_rotate_time
        logger.info('Next logfile rotate at '+ str(next_rotate))

With these mods the code works fine and the log file fred.log is rotated every minute producing fred.log.1 , fred.log.2 etc. as expected 使用这些mod,代码可以正常工作,并且日志文件fred.log每分钟旋转一次, fred.log.2按预期生成fred.log.1fred.log.2等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM