Python类中使用logging模块的最佳实践疑问
Python logging模块在多类场景下的最佳实践困惑
我最近在折腾Python的logging模块,对怎么用才最规范有点懵。我写了好几个类,想统一给它们加日志,还能一次性设置所有类的日志级别,目前试了两种思路,但都卡壳了:
我的两个尝试方向与困惑
- 全局共用同一个logger:但我的类是被框架调用的,没有一个统一的入口来定义主logger,这时候该怎么创建并添加handlers啊?
- 每个文件单独用一个logger:那这个logger是作为类属性,只在类第一次实例化的时候加handlers?还是在类定义前的导入部分就创建?之前看到过一篇教程不推荐这么做,但我没搞懂为啥。
另外,我查了好多logging基础用法的文档,但几乎找不到在类里面用的相关内容。补充一句:我觉得这不是重复问题,之前看到的已解决答案都是讲在主程序里加载配置,然后所有模块用,但我这情况是没有主程序啊,那配置该放哪儿?
针对你的问题的解决方案
关于全局共用logger的问题
其实logging模块本身就支持层级logger,你不需要刻意找一个"主入口"。可以这么做:
- 在每个类所在的模块里,用
logger = logging.getLogger(__name__)创建模块级别的logger。 - 然后在你的项目里找一个一定会被框架加载的初始化模块(比如框架的钩子函数、类的基类模块),在那里配置根logger的handlers和级别:
只要这个初始化函数在框架加载你的类之前被调用,所有模块的logger都会继承根logger的配置,实现统一管理。import logging def setup_logging(): # 先清空默认的handler,避免重复输出 for handler in logging.root.handlers[:]: logging.root.removeHandler(handler) # 添加自定义handler,比如控制台输出 console_handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_handler.setFormatter(formatter) logging.root.addHandler(console_handler) # 设置全局级别 logging.root.setLevel(logging.INFO)
关于每个文件单独用logger的问题
不推荐在导入阶段直接创建并配置logger,原因很简单:如果多个模块都这么做,会导致重复添加handlers,最终日志会被输出多次。比如模块A导入时加了一个控制台handler,模块B导入时又加了一个,那一条日志就会打两次。
正确的做法是:
- 在每个模块的顶部创建logger(
logger = logging.getLogger(__name__)),但不要在这里加handlers和设置级别。 - 把配置逻辑统一放到刚才说的初始化模块里,让所有logger继承根logger的配置。这样既保证每个模块有自己的logger名称(方便定位日志来源),又不会出现重复配置的问题。
如果一定要给某个类单独设置logger(比如需要特殊格式),可以在类的初始化方法里做,但要加个判断,避免重复添加handler:
class MyClass: _logger = None def __init__(self): if not self._logger: MyClass._logger = logging.getLogger(f"{__name__}.{self.__class__.__name__}") # 给这个logger单独加handler file_handler = logging.FileHandler('myclass.log') MyClass._logger.addHandler(file_handler) # 注意:如果不想继承根logger的级别,这里要单独设置 MyClass._logger.setLevel(logging.DEBUG)
没有主程序时的配置位置
如果你的代码是被框架调用的,那肯定有框架初始化的钩子点:
- 比如Django的
apps.py里的ready()方法 - Flask的
before_first_request装饰器 - 或者你自己写一个基类,让所有业务类继承这个基类,在基类的
__init_subclass__方法里完成日志配置(只执行一次)
只要找到这个框架会自动调用的初始化时机,把日志配置逻辑放进去就行,不需要传统意义上的"主程序"。
内容的提问来源于stack exchange,提问作者MeanStreet
相关产品推荐
相关产品推荐

