多次调用getLogger获取同名Python Logger后日志输出失效问题
为什么重复调用dictConfig后同名Logger无法输出日志?
问题根源
每次调用get_logger时都执行logging.config.dictConfig(yaml.safe_load(myconfig)),这会重置整个logging系统的配置,而你的配置里只定义了root Logger,没有显式配置__name__对应的Logger,导致后续获取的同名Logger无法输出日志:
- 第一次调用
get_logger(__name__):- 执行dictConfig完成root Logger的配置,同时创建
__name__对应的Logger实例——此时这个Logger默认会向父Logger(root)传播日志,所以10条"Test"能正常输出。
- 执行dictConfig完成root Logger的配置,同时创建
- 第二次在
tryme里调用get_logger(__name__):- 再次执行dictConfig时,系统会处理所有已存在的非root Logger(包括之前创建的
__name__Logger)。因为配置里没有这个Logger的条目,dictConfig会默认把它的propagate属性设为False,同时清空它的handlers。 - 此时新获取的Logger既没有自己的输出处理器,又不向root传播日志,自然无法输出内容。
- 再次执行dictConfig时,系统会处理所有已存在的非root Logger(包括之前创建的
而更换Logger名称能正常工作,是因为新名称的Logger是第一次创建,还没被dictConfig处理过,默认会向root传播日志,所以能正常输出。
解决方案
方案1:只初始化一次配置(推荐)
把dictConfig的调用移到函数外,整个程序只执行一次配置初始化:
import logging import logging.config import yaml myconfig = '''version: 1 formatters: simple: format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' handlers: standard_output: class: logging.StreamHandler formatter: simple stream: ext://sys.stdout root: level: DEBUG handlers: [standard_output] ''' # 全局只初始化一次日志配置 logging.config.dictConfig(yaml.safe_load(myconfig)) def get_logger(name): mylogger = logging.getLogger(name) return mylogger l = get_logger(__name__) for i in range(0, 10): l.error("Test") def tryme(msg): l = get_logger(__name__) l.error(msg) tryme("one") tryme("two")
方案2:在配置里显式定义目标Logger
如果必须多次执行dictConfig(不推荐这种做法),可以在配置中明确添加__name__对应的Logger条目,确保每次配置都能正确设置它:
# 注意:__main__是__name__在主程序中的实际值,若在模块中使用需替换为对应模块名 myconfig = '''version: 1 formatters: simple: format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' handlers: standard_output: class: logging.StreamHandler formatter: simple stream: ext://sys.stdout loggers: __main__: level: DEBUG propagate: True root: level: DEBUG handlers: [standard_output] '''
内容的提问来源于stack exchange,提问作者Morrico
相关产品推荐
相关产品推荐

