Python项目中模块日志无法传播至统一日志文件的原因及解决方法咨询
嗨,我来帮你把这个日志问题捋明白~你遇到的这个情况,核心是两个logger不在同一个传播链上,导致utils模块的日志没走到你配置的etl.log里。
先说说为啥会这样
当你直接运行script.py时,这个文件里的__name__变量值是__main__,所以你创建的logger名字是__main__;而utils/utils.py里的__name__是utils.utils,它的日志传播链是utils.utils → utils → 根logger(没有名字的顶层logger)。
日志的传播规则是:子logger会把日志往上传给父logger,但你只给__main__这个独立的logger加了FileHandler,utils.utils的日志会往上传给utils和根logger,可这俩都没配置输出handler,所以这些日志就“迷路”了,自然不会出现在你的etl.log里。你之前以为的传播逻辑,是默认入口脚本的logger是其他模块logger的父级,但实际上因为命名空间完全不同,它们是两条不相交的日志链,所以没法自动关联。
给你几个解决方法,按需选就行
方法一:配置根logger(最推荐,通用型强)
这是Python日志模块最标准的用法:在入口脚本(也就是你的script.py)里配置根logger,所有模块的日志最终都会顺着传播链走到根logger,被它的handler统一处理。修改script.py的日志配置部分:
import logging from utils.utils import load_query # 配置根logger(不传参数就是获取顶层根logger) logger = logging.getLogger() logger.setLevel(logging.INFO) file_handler = logging.FileHandler('etl.log') logger.addHandler(file_handler) logger.info("Starting") load_query() logger.info("Finished")
这样utils.utils里的日志会沿着utils.utils → utils → 根logger的路径传播,最终被根logger的FileHandler写入etl.log,你就能看到所有日志了。
方法二:让入口脚本的logger成为utils日志链的父级
如果你不想用根logger(比如怕和其他第三方库的日志混在一起),可以给入口脚本的logger指定一个顶层命名,然后让utils模块的logger成为它的子级。比如:
- 在
script.py里创建名为myproject的logger并配置:
# script.py import logging from utils.utils import load_query # 创建顶层项目logger logger = logging.getLogger("myproject") logger.setLevel(logging.INFO) file_handler = logging.FileHandler('etl.log') logger.addHandler(file_handler) logger.info("Starting") load_query() logger.info("Finished")
- 然后在
utils/utils.py里,使用这个顶层logger的子级:
# utils/utils.py import logging # 用顶层logger的子级名字 logger = logging.getLogger("myproject.utils.utils") def load_query(): logger.info("Running function")
这样myproject.utils.utils的日志会传给父级myproject,也就是你配置了handler的那个logger,日志就能正常输出了。
小提醒
不管用哪种方法,记得所有模块里的logger都保持默认的propagate=True(这是默认值,你没改的话就没问题),这样日志才能正常向上传播。另外,每个logger的级别要设置正确,你这里都设成了INFO,刚好能捕获所有INFO及以上级别的日志,这部分是没问题的~
这样应该就能解决你的问题啦,试试看看效果😉




