
本文介绍如何从 json 配置文件中正确读取日志级别(如 `"logging.info"`),并将其转换为 python `logging` 模块可识别的整数常量,避免因传入字符串导致 `valueerror: unknown level` 错误。
在实际项目中,将日志级别(如 INFO、DEBUG)存放在外部 JSON 配置文件中是一种常见做法,便于环境化管理。但直接将 "logging.INFO" 作为字符串读取后传递给 logger.setLevel() 会失败——因为 setLevel() 期望的是整数值(如 logging.INFO == 20),而非字符串字面量。
✅ 推荐方案:映射字典 + 安全校验
最清晰、安全且可维护的方式是构建一个显式的字符串到日志级别常量的映射字典:
import logging
import json
# 定义支持的日志级别映射(键可简化,不强制带 'logging.' 前缀)
LOG_LEVEL_MAP = {
"DEBUG": logging.DEBUG,
"INFO": logging.INFO,
"WARNING": logging.WARNING,
"WARN": logging.WARNING, # 兼容别名
"ERROR": logging.ERROR,
"CRITICAL": logging.CRITICAL,
"FATAL": logging.CRITICAL,
}
# 加载配置
with open("export_tool_config.json", "r") as f:
config = json.load(f)
log_level_str = config.get("loglevel", "INFO").strip().upper()
# 安全校验与转换
if log_level_str not in LOG_LEVEL_MAP:
raise ValueError(f"Unsupported log level '{log_level_str}' in config. "
f"Supported: {list(LOG_LEVEL_MAP.keys())}")
logger = logging.getLogger(__name__)
logger.setLevel(LOG_LEVEL_MAP[log_level_str])? 小技巧:logging 模块原生支持传入大写字符串(如 "INFO")——无需手动拼接 logging.INFO。因此 JSON 中建议直接写 "INFO",而非 "logging.INFO",更简洁、更健壮。
⚠️ 不推荐方式说明
- ❌ eval("logging.INFO") 或 exec():存在严重安全风险(任意代码执行),绝对禁止用于配置解析。
- ❌ getattr(logging, "INFO"):虽可行,但若输入非法(如 "INVALID")会抛出 AttributeError,不如字典映射易捕获和提示。
- ❌ 硬编码字符串比较链(if level == "INFO": ... elif level == "DEBUG": ...):可读性差、不易扩展。
✅ 最佳实践建议
-
JSON 配置示例(推荐):
{ "loglevel": "INFO", "output_dir": "./logs" } - 增强健壮性:使用 config.get("loglevel", "INFO") 提供默认值,并统一转为大写处理大小写混用问题。
- 日志初始化时添加 handler:仅设 level 不够,还需添加 StreamHandler 或 FileHandler 才能真正输出日志。
通过映射字典方式,你既能保持配置的可读性与灵活性,又能确保类型安全与运行时稳定性,是生产环境推荐的标准实践。










