Python 多模块项目中如何正确使用 logging(各模块共用配置)?

Python 多模块日志最佳实践:每个模块 logger = logging.getLogger(__name__),只在程序入口配置一次(basicConfig 或 fileConfig),子 logger 自动继承配置。

最佳实践
Python 多模块项目中如何正确使用 logging(各模块共用配置)?封面

标准模式:每个模块顶部写 logger = logging.getLogger(__name__)(不配置任何 handler);只在程序主入口配置一次 logging(basicConfig / fileConfig / dictConfig)。各模块的 logger 通过层级关系自动继承根配置。

各模块:只获取,不配置

# myapp/service.py
import logging

logger = logging.getLogger(__name__)

def process():
    logger.info("开始处理")

__name__ 让 logger 名称自动等于模块路径(如 myapp.service),日志里一眼看出消息来自哪个模块。

主入口:配置一次

# main.py
import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(name)s] %(levelname)s: %(message)s'
)

from myapp import service
service.process()

用配置文件管理(更灵活)

# main.py
import logging.config
logging.config.fileConfig('logging.conf', disable_existing_loggers=False)

logging.conf 示例:

[loggers]
keys=root

[handlers]
keys=console

[formatters]
keys=std

[logger_root]
level=INFO
handlers=console

[handler_console]
class=StreamHandler
formatter=std

[formatter_std]
format=%(asctime)s [%(name)s] %(levelname)s: %(message)s

常见错误

在模块里调用 basicConfig 或 addHandler——可能导致全局配置抢先或重复输出;basicConfig 在 root 已有 Handler 时通常不做任何事,并非总是覆盖。模块只管 getLogger(__name__),配置交给入口。

常见问题(FAQ)

Q:子 logger 和根 logger 什么关系?
A:myapp.service 是 myapp 的子 logger,myapp 又是 root 的子 logger。消息默认沿层级向上传递(propagate),记录在产生处通过有效级别/过滤器后才传播;传播途经的祖先 Logger 级别不再次筛选,Handler 自身级别仍生效,propagate=False 可截断传播。

Q:想单独调某个模块的日志级别?
A:logging.getLogger('myapp.db').setLevel(logging.DEBUG)——让 db logger 产生 DEBUG 记录,但仍需 Handler 级别放行;其他模块按其有效级别处理。

Q:第三方库的日志太吵?
A:logging.getLogger('urllib3').setLevel(logging.WARNING),同样利用命名层级。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台