如何通过环境变量切换logging.ini中定义的Python日志格式化器?
通过环境变量切换Python日志格式化器的解决方案
问题背景
我有如下logging.ini配置文件:
[loggers] keys=root [handlers] keys=consoleHandler [formatters] keys=simpleFormatter,json [logger_root] level=INFO handlers=consoleHandler [handler_consoleHandler] class=StreamHandler formatter=json args=(sys.stdout,) [formatter_json] class=pythonjsonlogger.jsonlogger.JsonFormatter format=%(asctime)s %(name)s %(levelname)s %(message)s [formatter_simpleFormatter] format=%(asctime)s %(name)s - %(levelname)s:%(message)s
尝试通过环境变量切换日志格式化器时,代码报错AttributeError: 'RootLogger' object has no attribute 'setFormatter',原代码如下:
import logging.config import os from pathlib import Path # 加载日志配置文件 logging_config_file_path = Path.joinpath( Path(__file__).parent.absolute(), "logging.ini" ) logging.config.fileConfig(logging_config_file_path) # 通过环境变量覆盖日志设置 LOGLEVEL = os.environ.get("LOGLEVEL", "INFO").upper() LOG_FORMATTER = os.environ.get("LOG_FORMATTER", "simpleFormatter").upper() LOGLEVEL_NUMBER = logging.getLevelName(LOGLEVEL) logger = logging.getLogger() logger.setLevel(LOGLEVEL) # 错误尝试:直接给logger设置格式化器 logger.setFormatter(LOG_FORMATTER)
另外尝试用defaults参数传递配置时,也出现解析错误:
修改后的logging.ini片段:
[handler_consoleHandler] class=StreamHandler # formatter=simpleFormatter formatter='%(formatter)s'
调用代码:
logging.config.fileConfig( logging_config_file_path, defaults={"formatter": "simpleFormatter"} )
报错信息:
configparser.InterpolationSyntaxError: bad interpolation variable reference '%(formatter)'
两种可行解决方案
方案一:加载配置后动态修改Handler的格式化器
报错核心原因:格式化器是绑定在Handler上的,而非Logger对象,不能直接调用logger.setFormatter()。正确步骤是找到Logger对应的Handler,再给Handler替换格式化器。
代码示例:
import logging.config import os from pathlib import Path # 加载日志配置文件 logging_config_file_path = Path.joinpath( Path(__file__).parent.absolute(), "logging.ini" ) logging.config.fileConfig(logging_config_file_path) # 读取环境变量 LOGLEVEL = os.environ.get("LOGLEVEL", "INFO").upper() LOG_FORMATTER_NAME = os.environ.get("LOG_FORMATTER", "simpleFormatter") # 修改日志级别 logger = logging.getLogger() logger.setLevel(LOGLEVEL) # 动态替换格式化器 for handler in logger.handlers: # 从日志管理器中获取已定义的格式化器对象 target_formatter = logging.getLoggerClass().manager.formatterDict.get(LOG_FORMATTER_NAME) if target_formatter: handler.setFormatter(target_formatter)
方案二:利用configparser插值加载时指定格式化器
之前的插值错误是因为给%(formatter)s加了多余的单引号,configparser的语法不需要引号。修改配置和代码如下:
修改后的logging.ini关键片段:
[handler_consoleHandler] class=StreamHandler formatter=%(formatter)s args=(sys.stdout,)
调用代码:
import logging.config import os from pathlib import Path # 从环境变量获取格式化器名称,默认用simpleFormatter LOG_FORMATTER_NAME = os.environ.get("LOG_FORMATTER", "simpleFormatter") # 加载配置时传入defaults参数,替换插值变量 logging_config_file_path = Path.joinpath( Path(__file__).parent.absolute(), "logging.ini" ) logging.config.fileConfig( logging_config_file_path, defaults={"formatter": LOG_FORMATTER_NAME}, disable_existing_loggers=False # 可选,保留已存在的日志实例 ) # 同时设置日志级别 LOGLEVEL = os.environ.get("LOGLEVEL", "INFO").upper() logger = logging.getLogger() logger.setLevel(LOGLEVEL)
内容的提问来源于stack exchange,提问作者red888
相关产品推荐
相关产品推荐

