2011-01-11 139 views
13

我在Python中使用日誌記錄模塊,我希望每次啓動應用程序時都會創建一個新的日誌文件。舊的日誌文件應該被旋轉(例如:logfile.txt - > logfile1.txt等)。每次啓動應用程序時旋轉日誌文件(Python)

我已經發現了這一點:

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

BaseRotatingHandler是旋轉的,在 某一點日誌文件處理程序的基類 。它並不意味着直接實例化 。相反,請使用 RotatingFileHandler或 TimedRotatingFileHandler。

RotatingFileHandler以預定大小進行翻轉,TimedRotatingFileHandler根據when和interval的乘積執行翻轉。兩者都不是我想要的,我希望輪換在我的應用程序啓動時立即發生。

回答

29

我可能已經足夠使用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

+1對於實際的解決方案。不幸的是,這個解決方案需要知道添加了哪些訂單處理程序 - 即my_logger.handlers [0] vs my_logger.handlers [n]。有沒有一種優雅的方式來避免避免硬編碼的價值? – 2013-07-29 22:56:25

+2

我很確定你可以調用handler.doRollover()。換句話說,在某處保持對它的引用。 – kylejmcintyre 2013-09-19 20:46:20

0

當應用程序運行很長時間(日子)並且希望日誌保持旋轉時,通常會設計和期望Log Rotation和RoatatingFileHandler。在重新啓動應用程序時必須旋轉日誌的情況下,我必須在日誌文件處理程序之外執行此操作,這很容易。就像在日誌寫入器第一次調用之前,我會看到日誌文件是否已經存在,如果是,請重命名並創建一個新的日誌文件。重命名應該與處理程序的重命名機制不同。

5

簡單的方法是要在日誌文件名的日期標籤,所以當你每次將獲得一個新的日誌文件,啓動應用程序。

例如

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有單獨的日誌爲每個應用程序調用,其中每個日誌本身被進一步劃分爲多個固定大小日誌。

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 

注:

  • 這已被證實在RotatingFileHandler如果maxBytes > 0工作。

  • 該方法尚未經過TimedRotatingFileHandler的測試,但應該有效。

  • 該方法無需保持對要旋轉的RotatingFileHandler的引用;因此,在使用logging.config配置日誌記錄時,可以輕鬆使用它。

相關問題