Python 日志记录创建空日志文件

Python logging creates empty log file

我正在尝试设置一个日志配置以在我的不同模块中使用。我按照不同的教程和 Whosebug 帖子 (here, here and here) 将日志写入 project.log 文件。

虽然信息在控制台中正确显示,但 log.conf 被正确读取,project.log 已创建但未填充警告消息。

我是这样处理的:

用于编写处理程序和格式的 log.conf 文件:

[loggers]
keys=root,sLogger

[handlers]
keys=consoleHandler,fileHandler

[formatters]
keys=fileFormatter,consoleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_sLogger]
level=DEBUG
handlers=consoleHandler,fileHandler
qualname=sLogger
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=WARNING
formatter=consoleFormatter
args=(sys.stdout,)

[handler_fileHandler]
class=FileHandler
level=WARNING
formatter=fileFormatter
args=('%(logfilename)s', 'w')

[formatter_fileFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

main.py 文件中:

import logging
import logging.config

def main():

    logging.config.fileConfig(fname='./log.conf', 
                                defaults={'logfilename': 'project.log')}, 
                                disable_existing_loggers=False)
    logger = logging.getLogger(__name__)

    logger.warning('This is a message')

在我的 module.py 文件中:

import logging
logger = logging.getLogger(__name__)

logger.warning('Example of a warning message')

我找到问题了!我没有意识到,但是在 log.conf 文件中定义 handlers 时,处理程序和格式化程序的顺序很重要!

我把log.conf改成了:

[loggers]
keys=root,sLogger

[handlers]
keys=consoleHandler,fileHandler

[formatters]
keys=consoleFormatter, fileFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler, fileHandler

[logger_sLogger]
level=DEBUG
handlers=consoleHandler, fileHandler
qualname=sLogger
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=WARNING
formatter=consoleFormatter
args=(sys.stdout,)

[handler_fileHandler]
class=FileHandler
level=WARNING
formatter=fileFormatter
args=('%(logfilename)s','a')

[formatter_fileFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s


[formatter_consoleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

请注意 [formatters] 部分中 consoleFormatterfileHandler 之间的更改顺序。

其余部分工作正常。

为了更容易玩,我把它放在一个函数中(我想这可能是多余的):

def base_logger(path_conf, fname, savedir):
    '''
    Base logging function to be started once
    in the main script then used in every other
    modules.

    Args:
        - path_conf: str, path to the configuration
        file {log.conf}
        - fname: str, name of the saved log file
        - savedir: str, path of the saving directory

    Returns:
        - logging object to be used in the other scripts

    Example:
        In main.py:
            main():
                base_logger(paht_cong = './log.conf', fname='file', savedir='project)
        
        In module.py:
            # AFTER all the import
            logger = logging.getLogger(__name__) # To ge the module name reported in the log file
            ...
            logger.error(f'Error message regarding variable {var}')

        The logger initialization {logger = logging.getLogger(__name__)},
         has to be done in every file that will use logging !

    '''
    logging.config.fileConfig(fname=path_conf,
                                defaults={'logfilename': os.path.join(savedir, f'{fname}.log')}, 
                                disable_existing_loggers=False)

我要补充一点,logger = logging.getLogger(__name__) 必须放在 imports 之后,以确保日志中显示的 module 名称不是从其他模块导入的。