2017-07-13 26 views
1

我有一個專門針對我的項目的通用記錄器實例。它會自動創建並附加2個處理程序(StreamHandlerTimedRotatingFileHandler),並預先配置不同的格式等。現在我是否需要在Python項目中的模塊之間共享記錄器實例?

logging_formatters = { 
    'fmt': "%(asctime)s [%(levelname)8s:%(process)05d] [%(module)10s:%(lineno)03d] (%(name)s) %(message)s", 
    'datefmt': "%Y-%m-%d %H:%M:%S" 
} 
def get_logger(
     application_name=None, 
     filename=None, 
     *args, 
     **kwargs 
): 
    if not isinstance(application_name, str): 
     raise ValueError("Logger class expects a string type application name") 

    if filename is None: 
     filename = application_name 

    if not filename.endswith(".log"): 
     filename = filename.split('.')[0] + ".log" 

    log_path = kwargs.get('log_path') 
    service_name = kwargs.get('service_name', '') 
    console_level = kwargs.get('console_level', logging.INFO) 
    file_level = kwargs.get('file_level', logging.DEBUG) 

    logger = logging.getLogger(application_name) 
    if len(logger.handlers) > 0: 
     return logger 
    # Create 2 handlers, and add them to the logger created 
    # ... 
    # ... 
    # ... 

,假設我的燒瓶項目的結構類似於:

/ 
- app.py 
- settings.py 
- dir1/ 
    - __init__.py 
    - mod1.py 
- dir2/ 
    - __init__.py 
    - mod2.py 

我開始使用python app.py服務器。 app.py本身導入了dir1.mod1dir2.mod2模塊。每個這些模塊的創建自己的記錄器實例如下:

logger = log_package.get_logger(
    application_name='{}.{}'.format(settings.APPLICATION_NAME, __name__), 
    filename=settings.LOG_FILE_NAME, 
    service_name=settings.SERVICE_NAME, 
) 

,並在app.py情況下,它是:

logger = log_package.get_logger(
    application_name='{}.{}'.format(settings.APPLICATION_NAME, 'run'), 
    filename=settings.LOG_FILE_NAME, 
    service_name=settings.SERVICE_NAME, 
) 

現在,我面臨的問題是; TimedRotatingFileHandler對於所有子模塊(即,dir1.mod1,dir2.mod2等)都正常工作,但app.py的日誌未被轉存到新文件。該特定實例將日誌寫入與服務啓動時相同的文件。例如。如果我在2017-07-11上啓動服務,則app.py將繼續將日誌寫入LOG_FILE_NAME.log.2017-07-11,而其他模塊每天都在滾動(when=midnight),並且新日誌正在寫入LOG_FILE_NAME.log

可能是背後的問題TimedRotatingFileHandler不適用於特定文件?我跑了目錄中的所有文件中的命令lsof,和這是輸出:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME 
python 23795 ubuntu 4w REG 202,1 2680401 150244 /path/to/LOG_FILE_NAME.2017-07-12 
python 23795 ubuntu 33w REG 202,1 397074 150256 /path/to/LOG_FILE_NAME.log 

我做需要跨模塊共享記錄器實例在Python項目?我認爲這不應該是必需的,因爲日誌模塊本身是線程安全的。

+0

我更新了我的答案。 –

回答

1

TimedRotatingHandler實例不應該寫入除LOG_FILE_NAME.log以外的文件 - 其他文件(如LOG_FILE_NAME.2017-07-12)將在滾動時創建,並且不應保持打開狀態。

對於給定的文件名,您應該確保在進程中只有一個TimedRotatingFileHandler實例 - 如果您有兩個不同的處理程序實例都引用相同的文件名,則可能會收到意外的行爲(如果一個實例翻轉,文件正在使用,但其他實例仍然會引用舊文件,並繼續寫入)。

您應該只是將您的處理程序附加到根記錄器而不是單個模塊記錄器,而其他記錄器會在默認條件(記錄器的默認propagate設置未更改)下選擇這些處理器。

更新:%(name)s總是給出用於日誌記錄調用的記錄器的名稱,即使處理程序連接到祖先記錄器。如果記錄器的propagate設置爲False,則不使用祖先記錄器中的處理程序 - 因此您應該將propagate保留爲默認值True

+0

但是我想用'%(name)s'來表示記錄器的名字。如果有人(我與幾個同事共享'log_package')正在創建一個項目'A',他們會將項目中的所有記錄器表示爲'A.app','A.dir1.mod1',...以及日誌文件總是爲'A.log'。在函數定義的最後,我重寫了傳播值:'logger.propagate = False'。我應該將'logger.propagate'重置爲'True'嗎? – hjpotter92

相關問題