You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 03:33:10