Python:从不同模块登录到同一文件的正确方法

2024-04-19 06:39:31 发布

您现在位置:Python中文网/ 问答频道 /正文

随着时间的推移,我已经编写了一堆脚本,我正在重构这些脚本以保留代码DRY。我目前在各种脚本中都使用了以下内容:

if __name__ == '__main__':
    logger = logging.getLogger('dbinit')
    hdlr = logging.FileHandler('/var/logs/tmp/foo.log')
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
    hdlr.setFormatter(formatter)
    logger.addHandler(hdlr) 
    logger.setLevel(logging.WARNING)

我不想在每个脚本(即“模块”)中重复这一点,而是希望在某个地方完成这个记录器初始化,并由各种脚本访问(嗯,也许包装在一个单例类中?)。

如果我不能这样做(即将记录器初始化代码放在一个核心模块中),我假设通过在logging.FileHandler()调用中使用相同的日志文件名,各种脚本将写入相同的文件。

这个假设正确吗?

最后但并非最不重要的是,解决这个问题的最佳实践(即Python)是什么?


Tags: 模块代码name脚本ifmainformatterlogging
3条回答

在python模块中创建如下函数:

def createLogHandler(job_name,log_file):
    logger = logging.getLogger(job_name)
    ## create a file handler ##
    handler = logging.FileHandler(log_file)
    ## create a logging format ##
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    return logger

现在调用程序中的函数,如下所示:

job_name = 'dbinit'
log_file = '/var/logs/tmp/foo.log'
logger = createLogHandler(job_name ,log_file )
logger.info('Logger has been created')

(...) addHandler() will not add a handler if the handler already exist所以在很多地方有这样的init代码不会有什么影响。

If I can't do that (i.e. put the logger initialisation code in one core module)

你可以这样做,如果你想确保初始化代码运行一次,你应该这样做。

鉴于您使用的是if __name__ == __main__,我假设这些脚本将作为不同的进程运行。如果是这种情况,那么应该使用单独的配置文件。

此配置可以按文档中指定的格式存储在文件中。然后,可以使用logging.config.fileConfig加载文件。您还可以将配置存储为JSON/YAML格式,将其转换为字典并使用logging.config.dictConfig加载。后者是当前推荐的方法,尽管我发现前者更为直截了当。阅读this了解更多信息。

使用配置文件方法的优点有很多:

  1. 它将配置设置与代码分开
  2. 它允许非程序员更改配置,因为它们以易于阅读的格式存储
  3. 它还可以防止你重复你已经提到过的你自己。

相关问题 更多 >