Python logging 如何让不同模块输出不同级别的日志
技术百科
舞夢輝影
发布时间:2026-01-25
浏览: 次 logging.getLogger(__name__)是关键,因它基于模块名自动构建层级logger树,支持各模块独立设level、handler及propagate=False,避免root干扰和日志重复或丢失。
为什么 logging.getLogger(__name__) 是关键
每个模块用 logging.getLogger(__name__) 获取独立 logger,而不是直接调用 logging.basicConfig() 或全局 logging.getLogger()。Python 的 logger 是按层级组织的(比如 a.b.c 是 a.b 的子 logger),__name__ 自动生成模块路径名,天然形成树状结构,为分级控制打下基础。
常见错误是全项目只用一个 root logger,结果改了某处级别,所有输出跟着变——这根本不是“不同模块不同级别”,只是全局开关。
如何给模块 A 设 INFO、模块 B 设 DEBUG
核心是分别获取、分别配置:不共享 handler,不共用 level,也不依赖 root 的传播(默认会向上传播到 root,造成干扰)。
- 在模块 A 开头写:
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)logger.addHandler(your_handler)logger.propagate = False # 关键!阻止向上送到 root - 在模块 B 开头写:
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)logger.addHandler(another_handler)logger.propagate = False - handler 可以复用(比如都用
StreamHandler),但 level 和 propagate 必须各自设
propagate=False 不设会怎样
如果不关掉 propagate,即使模块 B 的 logger 设了 DEBUG,它的日志仍会一路传到 root logger;而 root 默认是 WARNING 级别,结果 DEBUG 日志被 root 挡掉——你明明写了 logger.debug("test"),却什么也不输出,非常迷惑。
更糟的是,如果 root 已配了 handler(比如 basicConfig 已执行),那模块日志会重复打印两次:一次走自己的 handler,一次走 root 的 handler。
所以只要不是有意做日志聚合,每个模块 logger 都该显式加一句 logger.propagate = False。
有没有更省事的集中配置方式
有,用 dictConfig 一次性定义多个 logger,适合中大型项目。但要注意:字典里必须显式写出每个 logger 的 "propagate": False,否则默认仍是 True。
例如配置模块 foo.bar 为 DEBUG、baz 为 WARNING:
{
"version": 1,
"loggers": {
"foo.bar": {
"level": "DEBUG",
"handlers": ["console"],
"propagate": False
},
"baz": {
"level": "WARNING",
"handlers": ["file"],
"propagate": False
}
}
}这种写法干净,但调试时不如逐模块设来得直观;一旦 dict 配错(比如漏写

propagate),问题会藏得比较深。
# 的是
# 自己的
# 也不
# 写了
# 多个
# python
# 两次
# 一句
# stream
# 为什么
# gate
# 仍是
# asic
# 树状
# 都用
# Logging
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Python网络超时处理_健壮性设计说明【指导】
- 网站内页做seo排名怎么做?
- Win11怎么恢复出厂设置_Win11重置此电脑保
- php打包exe如何加密代码_防反编译保护方法【技
- php485读数据时阻塞怎么办_php485非阻塞
- 如何使用Golang编写单元测试_创建Test函数
- mac怎么打开终端_MAC终端Terminal使用
- XSLT怎么生成动态的HTML属性名和标签名
- php增删改查报错1054怎么办_字段名错误排查修
- c++怎么操作redis数据库_c++ hired
- Win11任务栏怎么调到左边_Win11开始菜单居
- PHP怎么接收前端传的时间戳_处理时间戳参数转换技
- Win11怎么把图标拖到任务栏_Win11固定应用
- VSC怎么配置PHP的Xdebug_远程调试设置步
- 如何在Golang中实现基础配置管理功能_Gola
- Python深度学习实战教程_神经网络模型构建与训
- VSC怎样在VSC中调试PHPAPI_接口调试技巧
- 如何在Golang中写入JSON文件_保存结构体数
- Win11怎么开启剪贴板历史记录_Windows1
- php查询数据怎么导出csv_查询结果转csv文件
- 如何在Golang中使用replace替换模块_指
- c++如何使用std::bind绑定函数参数_c+
- c++ std::atomic如何保证原子性 c+
- Win10如何关闭安全中心所有通知 Win10禁用
- Windows蓝屏BAD_POOL_HEADER故
- 如何在Golang中实现自定义Benchmark_
- 如何使用正则表达式批量替换重复的“-”模式为固定字
- Python字符串操作教程_切片拼接与格式化详解
- Win11怎么查看已连接wifi密码 Win11查
- Win10如何设置双wan路由器 Win10双wa
- Win11怎么更改任务栏颜色_Windows11个
- Win11怎么压缩文件 Win11自带压缩解压功能
- Win11怎么修改DNS服务器 Win11设置DN
- Win11怎么更改鼠标指针方案_Windows11
- c++如何用AFL++进行模糊测试 c++ Fuz
- Win11如何设置ipv6 Win11开启IPv6
- php怎么操作Redis_Redis扩展连接与基本
- Win11无法安装软件怎么办_Win11解除应用安
- PhpStorm怎么调试PHP代码_PhpStor
- Django 密码修改后会话失效的解决方案
- VSC里PHP变量未定义报错怎么解决_错误抑制技巧
- Python装饰器复用技巧_通用能力解析【教程】
- Windows 11登录时提示“用户配置文件服务登
- Win11怎么设置开机密码_Windows11账户
- Win11怎么设置任务栏透明_Windows11使
- Win11怎么关闭自动维护 Win11禁用系统自动
- 如何使用Golang sync.Map实现并发安全
- 微信JSAPI支付回调PHP怎么接收_处理JSAP
- php打包exe后无法写入文件_权限问题解决方法【
- php8.4如何调用com组件_php8.4win

QQ客服