Python从配置文件读取日志级别,避免前期DEBUG日志丢失的方案咨询
解决方案
方案1:内存缓存日志,确定最终级别后再输出
核心思路是先通过内存处理器临时缓存所有日志,等读取完配置文件、确定最终日志级别后,再初始化正式日志输出,并把缓存的日志重放进去,既不用修改日志文件,也能兼容控制台和文件日志。
步骤与代码示例:
- 先解析命令行里的配置文件路径(暂不处理日志级别参数)
- 初始化内存日志处理器,捕获所有DEBUG及以上日志
- 读取配置文件,合并命令行与配置的日志级别(命令行优先级更高)
- 初始化正式日志配置,重放缓存日志并移除临时处理器
import logging from logging.handlers import MemoryHandler # 1. 先解析配置文件路径(修改parseClArgs支持只提取必要参数) clArgs, progName = parseClArgs(__program__, only_config_path=True) # 2. 初始化临时内存日志处理器,捕获所有日志 temp_handler = MemoryHandler(capacity=1024) temp_handler.setLevel(logging.DEBUG) root_logger = logging.getLogger() root_logger.addHandler(temp_handler) root_logger.setLevel(logging.DEBUG) # 此时打日志都会存在内存中 logging.debug(f"Directory where the Program is being executed: {PROGRAM_DIR}") # 3. 读取配置文件 programConfig = readProgramConfig(clArgs.programConfigPath) # 4. 确定最终日志级别 final_log_level = logging.INFO # 命令行指定的级别优先 if hasattr(clArgs, 'logLevel') and clArgs.logLevel is not None: final_log_level = getattr(logging, clArgs.logLevel) # 其次用配置文件的级别 elif 'log_level' in programConfig: final_log_level = getattr(logging, programConfig['log_level']) # 5. 初始化正式日志配置(修改configLogging支持传入级别参数) defaultLogFilePath = configLogging(final_log_level) # 6. 重放缓存日志到正式处理器,清理临时处理器 temp_handler.setTarget(root_logger.handlers[0]) temp_handler.flush() root_logger.removeHandler(temp_handler) # 后续日志正常输出 logging.info(f"Program version: {__program__.swVersion}") logging.info(f"Program start time: {programStartDate}") logging.debug(f"Log file location: {defaultLogFilePath}")
方案2:先读配置文件,再合并命令行参数
调整流程顺序,先拿到配置文件路径并读取配置,再用配置里的日志级别作为命令行参数的默认值,最后一次性初始化日志,从根源避免先后问题。
步骤与代码示例:
- 第一次解析命令行,只提取配置文件路径
- 读取配置文件,获取配置中的日志级别
- 第二次解析完整命令行参数,用配置级别作为日志参数的默认值
- 用最终参数初始化日志
# 1. 第一次解析,仅获取配置文件路径 clArgs_first, _ = parseClArgs(__program__, only_config_path=True) # 2. 读取配置文件 programConfig = readProgramConfig(clArgs_first.programConfigPath) config_log_level = programConfig.get('log_level', 'INFO') # 3. 第二次解析完整参数,将配置级别设为日志参数的默认值 clArgs, progName = parseClArgs(__program__, default_log_level=config_log_level) # 4. 初始化日志 defaultLogFilePath = configLogging(clArgs) # 所有日志按最终级别正常记录 logging.info(f"Program version: {__program__.swVersion}") logging.info(f"Program start time: {programStartDate}") logging.debug(f"Directory where the Program is being executed: {PROGRAM_DIR}") logging.debug(f"Log file location: {defaultLogFilePath}")
需要修改parseClArgs函数,支持传入默认日志级别:
def parseClArgs(program, only_config_path=False, default_log_level='INFO'): parser = argparse.ArgumentParser(prog=program.name) if not only_config_path: parser.add_argument( "-l", "--loglevel", help="Set the logging level of the program. Defaults to config value or 'INFO'.", default=default_log_level, dest="logLevel", choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] ) parser.add_argument( "-c", "--config", help="Path to program configuration file", dest="programConfigPath", required=True ) args = parser.parse_args() return args, program.name
方案3:动态调整日志级别(最简方案,有 trade-off)
如果可以接受"前期DEBUG日志在最终级别为INFO时会被记录下来",那可以先以DEBUG级别初始化日志,读取配置后再调整根日志级别,实现成本最低。
# 1. 解析所有命令行参数 clArgs, progName = parseClArgs(__program__) # 2. 先以DEBUG级别初始化日志,捕获所有内容 defaultLogFilePath = configLogging(logging.DEBUG) # 打前期日志 logging.debug(f"Directory where the Program is being executed: {PROGRAM_DIR}") # 3. 读取配置文件 programConfig = readProgramConfig(clArgs.programConfigPath) # 4. 确定最终级别 final_log_level = getattr(logging, clArgs.logLevel) if clArgs.logLevel != 'INFO' else getattr(logging, programConfig.get('log_level', 'INFO')) # 5. 调整根日志级别 logging.getLogger().setLevel(final_log_level) # 后续日志按最终级别输出 logging.info(f"Program version: {__program__.swVersion}") logging.info(f"Program start time: {programStartDate}") logging.debug(f"Log file location: {defaultLogFilePath}") # 若最终为INFO,这条不会输出
内容的提问来源于stack exchange,提问作者SimpleThings
相关产品推荐
相关产品推荐

