如何通过logging模块在多文件中复用同一自定义日志实例
跨模块复用自定义日志实例的解决方案
针对你遇到的问题,这里提供三种实用的解决思路,无需让file_two预先知晓调用方的配置:
方案1:利用日志器层级继承(最简单)
Python的logging模块采用层级结构,子日志器会自动继承父日志器(包括根日志器)的handler和级别配置。你可以在入口文件file_one中直接配置根日志器,file_two中创建的日志器会自动复用该配置。
修改file_one.py:
import logging from logger import create_file_handler # 获取全局根日志器 root_logger = logging.getLogger() root_logger.setLevel(logging.INFO) # 添加自定义文件handler file_handler = create_file_handler(r'C:\custom\path', filename="custom_filename") root_logger.addHandler(file_handler) # 入口文件自身日志示例 root_logger.info("这是来自file_one的日志")
file_two.py无需额外配置,直接创建当前模块的日志器即可:
import logging # 获取当前模块日志器,自动继承根日志器配置 logger = logging.getLogger(__name__) def some_function(): logger.info("这条日志会自动写入file_one指定的日志文件")
方案2:显式传递日志实例(灵活可控)
如果不想全局统一配置,可在调用file_two的函数时,将自定义日志实例作为参数传递,file_two优先使用传入的实例,无传入则使用默认配置。
修改file_two.py:
import logging from logger import create_file_handler def _get_default_logger(): """创建默认日志器(仅无传入实例时使用)""" logger = logging.getLogger(__name__) # 避免重复添加handler,检查是否已有配置 if not logger.handlers: default_handler = create_file_handler(r'默认日志路径') logger.setLevel(logging.INFO) logger.addHandler(default_handler) return logger def some_function(logger=None): # 优先使用传入实例,否则用默认 current_logger = logger or _get_default_logger() current_logger.info("根据调用方传入的实例记录日志")
file_one.py调用时传递日志实例:
import logging from logger import create_file_handler from file_two import some_function # 创建自定义日志实例 file_handler = create_file_handler(r'C:\custom\path', filename="custom_filename") le_log = logging.getLogger(__name__) le_log.setLevel(logging.INFO) le_log.addHandler(file_handler) # 调用file_two函数时传递日志实例 some_function(logger=le_log)
方案3:全局单例日志器(严格复用同一实例)
在logger.py中维护一个全局单例日志实例,入口文件先初始化配置,其他模块直接获取该实例即可。
修改logger.py:
import logging import os from concurrent_log_handler import ConcurrentRotatingFileHandler # 全局单例日志实例 _global_logger = None def init_custom_logger(path, filename=None): """初始化自定义日志器(单例模式)""" global _global_logger if _global_logger is not None: return _global_logger # 已初始化直接返回 if filename is None: filename = f"app_{os.getlogin()}" formatter = logging.Formatter('%(asctime)s | %(name)s | %(funcName)s | %(levelname)s | %(message)s') file_handler = ConcurrentRotatingFileHandler(fr'{path}\{filename}.log', mode='a', maxBytes=1024*1024*10, backupCount=10) file_handler.setLevel(logging.INFO) file_handler.setFormatter(formatter) _global_logger = logging.getLogger("custom_global_logger") _global_logger.setLevel(logging.INFO) _global_logger.addHandler(file_handler) return _global_logger def get_logger(): """获取全局日志实例,未初始化则用默认配置""" global _global_logger if _global_logger is None: # 默认初始化逻辑,可按需调整 return init_custom_logger(r'默认日志路径') return _global_logger
file_one.py中初始化:
from logger import init_custom_logger # 初始化全局日志器 le_log = init_custom_logger(r'C:\custom\path', filename="custom_filename") le_log.info("入口文件的自定义日志")
file_two.py中直接获取:
from logger import get_logger logger = get_logger() def some_function(): logger.info("复用全局单例日志的配置")
内容的提问来源于stack exchange,提问作者TmSmth
相关产品推荐
相关产品推荐

