Python logging 正确配置:告别 print 调试与日志重复打印

发布时间:2026/7/20 14:06:07

Python logging 正确配置:告别 print 调试与日志重复打印
Python logging 正确配置:告别 print 调试与日志重复打印线上服务出问题,你翻日志却发现:要么啥都没有(全靠print早被丢进 stdout 黑洞),要么同一条日志打了三遍,要么日志文件涨到几个 G 把磁盘撑爆。Python 的logging模块功能齐全,但默认行为反直觉,踩坑的人比用对的人多。这篇把生产级 logging 配置一次讲清:为什么别用 root logger、怎么避免重复打印、怎么按大小/时间轮转文件。别再用 print,也别只会 logging.info很多人对 logging 的认知停留在import logging; logging.info(xxx)。这行代码用的是root logger,问题在于:importlogging logging.info(这条你根本看不到)# 默认级别是 WARNING,INFO 被丢弃logging.warning(这条才会打印)默认级别是WARNING,所以info/debug直接被吞。更重要的是,在 root logger 上乱配置会污染所有第三方库的日志。正确姿势是每个模块拿自己的 logger:importlogging# 惯例:用模块名做 logger 名字,自动形成层级loggerlogging.getLogger(__name__)defdo_work():logger.info(开始处理)# 名字会是 myapp.service 这种logging.getLogger(__name__)让日志自带来源(哪个模块打的),而且 logger 名字用.分隔会形成父子层级,后面配置时能按模块精细控制。一个能用的基础配置在程序入口(如main.py)集中配一次,其他模块只管getLogger(__name__)拿来用:importloggingimportsysdefsetup_logging(levellogging.INFO):loggerlogging.getLogger()# 拿 root logger 做统一配置logger.setLevel(level)# Handler 决定日志去哪:这里输出到 stderrhandlerlogging.StreamHandler(sys.stderr)# Formatter 决定长什么样:时间 级别 模块 消息fmtlogging.Formatter(%(asctime)s [%(levelname)s] %(name)s: %(message)s,datefmt%Y-%m-%d %H:%M:%S,)handler.setFormatter(fmt)logger.addHandler(handler)if__name____main__:setup_logging()logging.getLogger(__name__).info(服务启动)# 输出: 2026-07-20 09:00:00 [INFO] __main__: 服务启动三个核心概念理清:Logger是你调用的入口、Handler决定日志输出到哪(控制台/文件/网络)、Formatter决定每条长什么样。一个 Logger 可以挂多个 Handler,同时输出到控制台和文件。头号大坑:日志重复打印配置完跑起来,发现每条日志打了两遍甚至三遍——这是 logging 最经典的坑。根因通常是handler 被重复添加,或者子 logger 的消息向上传播到 root 又被打了一遍。第一种,setup_logging被调了多次(比如在循环或被重复 import 的模块里):defsetup_logging():loggerlogging.getLogger()# 危险:每调一次就多挂一个 handler,日志翻倍logger.addHandler(logging.StreamHandler())修复:加之前先清空,或判断是否已有 handler:defsetup_logging():loggerlogging.getLogger()iflogger.handlers:# 已经配过就别再挂了returnlogger.addHandler(logging.StreamHandler())第二种,你给某个模块 logger 单独挂了 handler,但它的消息默认还会propagate 到 root,root 上也有 handler,于是打两遍:mod_loggerlogging.getLogger(myapp.worker)mod_logger.addHandler(logging.StreamHandler())# 消息会:先被自己的 handler 打一遍,再冒泡到 root 又打一遍mod_logger.propagateFalse# 关掉冒泡,只打一遍记住:要么只在 root 上配 handler、子 logger 靠冒泡输出;要么给子 logger 单独配 handler 并关掉 propagate。别两头都挂。文件轮转:别让日志把磁盘撑爆生产日志写文件,必须轮转,否则单文件无限增长。标准库自带两种 handler,不用装任何东西。按文件大小轮转,单文件 10MB、保留 5 个历史:fromlogging.handlersimportRotatingFileHandler handlerRotatingFileHandler(app.log,maxBytes10*1024*1024,# 单文件 10MBbackupCount5,# 超了就滚动,最多留 app.log.1 ~ .5encodingutf-8,)按时间轮转,每天午夜切一个新文件、保留 7 天:fromlogging.handlersimportTimedRotatingFileHandler handlerTimedRotatingFileHandler(app.log,whenmidnight,# 每天午夜滚动;也可 H(每小时)、W0(每周一)backupCount7,# 保留最近 7 天encodingutf-8,)按天轮转更适合排查(一天一个文件好定位),按大小轮转更适合控制磁盘占用。两者选一即可,别叠加。一个实用技巧:异常带堆栈记录异常时,别只logger.error(str(e))——那样丢了堆栈,等于没记。用exc_infoTrue或直接logger.exception:try:risky()exceptException:# exception() 等价于 error(..., exc_infoTrue),自动带完整 tracebacklogger.exception(处理失败)# 只能在 except 块里用logger.exception会把完整 traceback 一起写进日志,排查线上问题时这几行堆栈往往就是关键。注意它只在except块里用才有意义。小结每个模块用logging.getLogger(__name__),别直接用 root logger 或logging.info。理清Logger / Handler / Formatter三者职责:入口、去哪、长啥样。日志重复打印几乎都是 handler 重复添加或 propagate 冒泡导致,给子 logger 配了 handler 就设propagate False。写文件必用RotatingFileHandler(按大小)或TimedRotatingFileHandler(按时间)轮转,别让单文件无限涨。记异常用logger.exception,带上堆栈才有排查价值。一句话记忆点:日志打两遍先查 handler 挂了几个、propagate 关没关;这是 logging 最省时间的一条排查经验。

相关新闻

CTF命令注入实战:绕过空格与关键词过滤的Shell技巧

CTF命令注入实战:绕过空格与关键词过滤的Shell技巧

2026/7/20 14:06:07

1. 项目概述:一次典型的命令注入挑战在CTF(Capture The Flag,夺旗赛)的Web安全赛道上,命令注入(Command Injection)是经久不衰的经典题型。它模拟了攻击者如何通过Web应用接口,将恶意…

终极指南:如何使用HackBrowserData跨平台提取与解密浏览器数据

终极指南:如何使用HackBrowserData跨平台提取与解密浏览器数据

2026/7/20 14:06:07

终极指南:如何使用HackBrowserData跨平台提取与解密浏览器数据 【免费下载链接】HackBrowserData Extract and decrypt browser data, supporting multiple data types, runnable on various operating systems (macOS, Windows, Linux). 项目地址: https://gitco…

如何快速实现渐进式图片加载:vue-progressive-image与Vue 3 Composition API的完美结合

如何快速实现渐进式图片加载:vue-progressive-image与Vue 3 Composition API的完美结合

2026/7/20 13:56:07

如何快速实现渐进式图片加载:vue-progressive-image与Vue 3 Composition API的完美结合 【免费下载链接】vue-progressive-image Vue progressive image loading plugin 项目地址: https://gitcode.com/gh_mirrors/vu/vue-progressive-image 在现代Web开发中…

Python age-detection-local 包:功能详解、安装使用与实战案例

Python age-detection-local 包:功能详解、安装使用与实战案例

2026/7/21 8:17:14

1. 引言在计算机视觉领域,年龄检测是一项经典且实用的任务。Python 的 age-detection-local 包为开发者提供了一套轻量级、本地化的年龄估计解决方案,无需依赖云端 API,即可在本地设备上快速完成人脸年龄预测。本文将详细介绍该包的功能特性、…

香港数码港正在成为中国AI出海的「跳板」

香港数码港正在成为中国AI出海的「跳板」

2026/7/21 8:17:14

作者|周雅在中国香港的南部,有一个坐标广为人知,它就是当地知名的科技园区——“数码港”。智谱2025年入驻数码港,一年后在港交所敲响“全球大模型第一股”的开市锣;云迹科技落地数码港短短一年,海外营收增…

CTF实战:从ZIP文件修复到AES-CBC解密的完整MISC取证流程

CTF实战:从ZIP文件修复到AES-CBC解密的完整MISC取证流程

2026/7/21 8:17:14

1. 项目概述:一次典型的MISC取证与密码学实战 最近在复盘DASCTF 2024的一道MISC题目,整个过程堪称一次小型数字取证与密码学分析的微缩演练。题目本身并不复杂,但串联了文件格式修复、隐写分析、密码破解等多个MISC领域的经典考点&#xff0c…

树结构解析:从二叉树到B+树的工程实践

树结构解析:从二叉树到B+树的工程实践

2026/7/21 8:17:14

1. 从家族树到数据结构:树的本质解析 第一次接触"树"这个概念是在大学数据结构课上,教授用家谱图举例时,我突然意识到这种分叉结构在计算机世界和现实生活中无处不在。家族树中每个人只有一个父亲但可能有多个孩子,这种…

Claude Code隐写术事件解析与开发者应对指南

Claude Code隐写术事件解析与开发者应对指南

2026/7/21 8:17:14

1. Claude Code隐写术事件概述最近AI编程工具领域爆出一个重大安全事件:Anthropic公司开发的Claude Code被曝在客户端植入隐写逻辑,通过特殊编码方式收集用户环境信息。这一发现由开发者AdnaneKhan在分析Claude Code编译后的二进制文件时揭露&#xff0c…

如何用Python自动化工具实现B站会员购抢票:终极完整指南

如何用Python自动化工具实现B站会员购抢票:终极完整指南

2026/7/21 8:07:14

如何用Python自动化工具实现B站会员购抢票:终极完整指南 【免费下载链接】biliTickerBuy b站会员购购票辅助工具 项目地址: https://gitcode.com/GitHub_Trending/bi/biliTickerBuy B站会员购抢票总是一票难求?手动操作总是慢人一步?今…

微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

2026/7/21 5:45:57

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

2026/7/20 2:33:13

一、零售门店全域协同业务背景与行业痛点 1.1 门店超级终端设备矩阵(连锁便利店/商超标准配置) 自助收银Kiosk一体机:顾客结算、自助核销优惠券、商品素材预览;运营折叠平板:店长后台商品上新、图片录入、活动配置、…

噗叽短视频界面分析

噗叽短视频界面分析

2026/7/21 3:09:32

1 和小红书类似,可以采用类似判断方法------------其实他比小红书好判断,因为他没有图片,控件位置几乎是固定的,都不用判断------------2 因为他没有点赞按钮------------而且几乎所有控件位置都是完全一样的,所以我就…

GraphRAG Local + Ollama:微软知识图谱本地化

GraphRAG Local + Ollama:微软知识图谱本地化

2026/7/21 0:06:35

普通 RAG 有个老毛病:你问它「这堆文档整体在讲什么」,它答不上来。因为它只会把问题切成向量,去几十个文本块里捞最相似的几段拼给模型看。可「整体讲什么」这种问题,答案根本不在任何单独一段里——它散在全篇的联系里。 微软的…

AI 数据产品化思考:让分析能力变成可售卖的数据服务

AI 数据产品化思考:让分析能力变成可售卖的数据服务

2026/7/21 0:06:35

AI 数据产品化思考:让分析能力变成可售卖的数据服务 大家好,我是朱大喜。这周一直在复盘具体的项目和技术,最后一篇聊点不一样的东西——数据产品化。做了这么多年数据分析,我发现一个规律:能卖出去的从来不是"分…

基于人机协作的 AI 研发新体系架构:从 Harness 工程到 Loop 工程实践

基于人机协作的 AI 研发新体系架构:从 Harness 工程到 Loop 工程实践

2026/7/21 0:06:35

本文完整呈现了企业级 AI Coding 落地的核心方法论:从 Harness 工程的微观/宏观定义,到 Loop 工程的六大构建模块,再到基于 SDD(规范驱动开发)的工程化落地路径。干货较多,建议收藏细读。 我从 22 年开始就…