每次启动应用程序时都旋转日志文件(Python)

时间:2011-01-11 06:44:06

标签: python logging rotation

我在Python中使用日志记录模块,我希望每次启动应用程序时都创建一个新的日志文件。应该旋转旧的日志文件(例如:logfile.txt - > logfile1.txt等)。

我已经发现了这个:

http://docs.python.org/library/logging.html

  

BaseRotatingHandler是基类   用于旋转日志文件的处理程序   某一点。它并不意味着   直接实例化。相反,使用   RotatingFileHandler或   TimedRotatingFileHandler。

RotatingFileHandler以预定大小进行翻转,TimedRotatingFileHandler根据when和interval的乘积进行翻转。两者都不是我想要的,我希望在我的应用程序启动时立即发生轮换。

4 个答案:

答案 0 :(得分:31)

我可能只使用RotatingFileHandler而不使用maxBytes,然后在应用程序启动时调用doRollover()

是的,似乎工作正常。下面的代码将在每次运行应用程序时创建一个新的日志文件,并为日志开始和关闭时间添加时间戳。运行它将打印可用日志文件列表。您可以检查它们以检查正确的行为。改编自Python文档示例:

import os
import glob
import logging
import logging.handlers
import time

LOG_FILENAME = 'logging_rotatingfile_example.out'

# Set up a specific logger with our desired output level
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)

# Check if log exists and should therefore be rolled
needRoll = os.path.isfile(LOG_FILENAME)

# Add the log message handler to the logger
handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, backupCount=50)

my_logger.addHandler(handler)

# This is a stale log, so roll it
if needRoll:    
    # Add timestamp
    my_logger.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime())

    # Roll over on application start
    my_logger.handlers[0].doRollover()

# Add timestamp
my_logger.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime())

# Log some messages
for i in xrange(20):
    my_logger.debug('i = %d' % i)

# See what files are created
logfiles = glob.glob('%s*' % LOG_FILENAME)

print '\n'.join(logfiles)

答案 1 :(得分:6)

最简单的方法就是在日志文件名中添加日期标记,因此每次启动应用程序时都会获得新的日志文件。

e.g。

dateTag = datetime.datetime.now().strftime("%Y-%b-%d_%H-%M-%S")
logging.basicConfig(filename="myapp_%s.log" % dateTag, level=logging.DEBUG)

所以每次你都会有像myapp_2011-Jan-11_12-27-29.log

这样的日志

另一个好处是你可以将它与RotatingFileHandler混合使用,为每个应用程序调用提供单独的日志,其中每个日志本身进​​一步分为多个固定大小的日志。

答案 2 :(得分:0)

当应用程序运行很长时间(天)并且您希望日志保持轮换时,通常会设计并且需要Log Rotation和RoatatingFileHandler。在我必须在重新启动应用程序时旋转日志的情况下,我必须在Logfile处理程序之外执行此操作,这更容易。就像在第一次调用日志编写器之前,我会看到日志文件是否已经存在,如果是,则重命名它并创建一个新的日志文件。重命名应该与处理程序的重命名机制区分开来。

答案 3 :(得分:0)

我有一个类似的要求,可以在启动时根据命令行选项强制执行日志轮换,但是日志文件会按照常规计划轮换。这是我的解决方案:

import logging

from logging.handlers import BaseRotatingHandler
from typing import Union

def rotate_logs(loggers: Union[str,list]=None, delimiter: str=','):
    """Rotate logs.

    Args:
        loggers: List of logger names as list object or as string,
            separated by `delimiter`.

        delimiter: Separator for logger names, if `loggers` is :obj:`str`.
            Defaults to ``,`` (comma).

    """

    # Convert loggers to list.
    if isinstance(loggers, str):
        loggers = [t.strip() for t in loggers.split(delimiter)]

    handlers = []
    root = logging.getLogger()

    # Include root logger in dict.    
    ld = {'': root, **root.manager.loggerDict}

    for k, v in ld.items():
        if loggers is not None and k not in loggers:
            continue

        try:
            for h in v.handlers:
                if (isinstance(h, BaseRotatingHandler) and
                    h not in handlers):

                    handlers.append(h)

        except AttributeError:
            pass

    for h in handlers:
        h.doRollover()



if __name__ == '__main__':
    pass

备注:

  • 如果maxBytes > 0 RotatingFileHandler上有TimedRotatingFileHandler,则此功能已经过验证。

  • 此方法尚未使用RotatingFileHandler进行测试,但应该有效。

  • 此方法无需维护对要旋转的logging.config的引用;因此,在使用template<class T> void func(T* buf); //template I template<size_t N> void func(char (&buf) [N]); //template II void g(char (&buf)[3]) { func(buf) //Error: ambiguous function call (Clang, GCC, ICC, MSVC) } 配置日志记录时可以轻松使用它。