不要再用 print() 了!Python logging 库才是调试的终极武器

大家好,今天咱们来聊一个能直接让你少掉几根头发的神器------Python logging 库

你是不是经常这样: 代码写到一半,逻辑有点乱,于是手一抖,敲下了熟悉的 print("debug...")。结果越写越乱,满屏幕的输出让人眼睛花;调试完还得一个个删掉,不删吧心里不踏实,删吧又怕删漏。最后,整个人被"print调试"折磨到怀疑人生。

别问我为什么懂,我也曾是 print() 调试的受害者。

后来,我遇到了 logging 库,那一刻我才发现:原来调试也能这么优雅!

今天,我就带你彻底搞懂 logging 库------从入门到进阶,从基础配置到自定义类。保证你看完之后,代码调试思路清爽到飞起,再也不用和 print() 苦苦纠缠。


1. 为什么 print() 不够用?

说实话,print() 并不是完全没用,它就像炒菜时的"生抽",偶尔点缀一下能提味。

但是!如果你把整道菜全靠"生抽"撑着,那只会变成一锅咸汤。

举个例子: 你写了 200 行代码,里面夹杂了 30 个 print(),运行的时候屏幕刷得比股市行情还快。调试完你还得手动删除,万一漏掉几个,可能上线之后还傻乎乎地往控制台狂输出。

更要命的是,print() 输出的内容一锅乱炖,没有级别、没有格式,查问题的时候就像在大海捞针。

logging 库 就不一样了,它能帮你:

  • 分级别输出日志:调试信息、警告、错误一清二楚。
  • 定义输出格式:带时间、带模块名,看着就舒服。
  • 保存到文件:以后回溯问题,不用苦逼地翻控制台历史。
  • 多路输出:想控制台看,还是文件看,随便你。

一句话总结:logging 是调试的艺术,print 只是临时凑合。


2. logging 的"Hello World"

先别怕复杂,我们从最简单的例子开始。

python 复制代码
import logging

# 设置基本配置,日志级别为DEBUG
logging.basicConfig(level=logging.DEBUG)

# 输出一条INFO级别的日志
logging.info('这是一条信息日志')

# 输出一条DEBUG级别的日志
logging.debug('这是一条调试日志')

# 输出一条WARNING级别的日志
logging.warning('这是一条警告日志')

# 输出一条ERROR级别的日志
logging.error('这是一条错误日志')

# 输出一条CRITICAL级别的日志
logging.critical('这是一条严重错误日志')

运行一下,输出类似这样:

less 复制代码
INFO:root:这是一条信息日志
DEBUG:root:这是一条调试日志
WARNING:root:这是一条警告日志
ERROR:root:这是一条错误日志
CRITICAL:root:这是一条严重错误日志

看到没?光是比 print(),它就已经高级太多了。

这里有个重点: 日志级别是有优先级的,从低到高分别是: DEBUG < INFO < WARNING < ERROR < CRITICAL

比如你把日志级别设置成 ERROR,那么 DEBUG、INFO、WARNING 就不会输出,只有 ERROR 和 CRITICAL 才会被打印出来。是不是很灵活?


3. 日志级别背后的"小心机"

有同学可能会问:这些日志级别到底该怎么用?

我来给你套个生活里的比喻:

  • DEBUG:就像你在厨房里自言自语,"这火是不是小了点?再放点盐试试。"------全是内部小碎碎念。
  • INFO:类似你对朋友说:"这道菜大体还行,能吃。"------正常的状态汇报。
  • WARNING:就像你妈在旁边提醒你:"油烟太大,小心呛着。"------不致命,但要注意。
  • ERROR:相当于你炒菜时锅糊了,菜还能救,但味道打折。
  • CRITICAL:锅直接着火了,别炒了,赶紧灭火吧!

是不是一下就记住了?


4. 给日志加点"排面":自定义格式

默认日志的样子有点单调,光是 INFO:root:xxx 难免乏味。

logging 支持自定义格式,比如加上时间、日志级别、消息内容,看着更清晰:

ini 复制代码
import logging

# 设置日志格式
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logging.debug('这是一条调试日志')
logging.info('这是一条信息日志')

输出效果:

yaml 复制代码
2025-01-12 10:23:56,123 - root - DEBUG - 这是一条调试日志
2025-01-12 10:23:56,124 - root - INFO - 这是一条信息日志

是不是更有"专业感"了? 在公司项目里,这种带时间戳的日志特别重要,出了问题直接一眼能定位是哪一刻发生的。


5. 日志写入文件:让 Bug 留下"案底"

现实场景里,光看控制台不够。你下班了,服务器还在跑,出了问题你也得有证据。

这时候,就要把日志写到文件里:

ini 复制代码
import logging

# 将日志记录到文件
logging.basicConfig(level=logging.DEBUG,
                    filename='app.log',
                    format='%(asctime)s - %(levelname)s - %(message)s')

logging.info('这条日志会被写入到文件中')

运行完后,你会发现当前目录下多了一个 app.log 文件,里面乖乖地躺着日志。

这就是"案底"。哪怕你过几天才回头看,也能找到问题发生的全过程。


6. 高级玩法:多处理器 + 格式化

如果你想要"既输出到控制台,又保存到文件",那就得用到 logger、handler、formatter 这套组合拳了。

看代码:

ini 复制代码
import logging

# 创建logger对象
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)

# 创建一个控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)

# 创建一个文件处理器
file_handler = logging.FileHandler('my_log.log')
file_handler.setLevel(logging.DEBUG)

# 创建formatter并将其设置到处理器
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

# 将处理器添加到logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)

# 测试日志输出
logger.debug('调试信息')
logger.info('普通信息')
logger.warning('警告信息')

这样,你就能一边在控制台看实时日志,一边在文件里存历史记录,互不耽误。

这可是大型项目的标配操作。


7. 封装一个属于自己的 Log 类

到这里,你可能觉得配置 handler、formatter 有点繁琐。

没关系,我们可以自己封装一个 Log 类,把这些细节都打包好,直接复用。

python 复制代码
import logging

class Log:
    def __init__(self, name="my_logger", level=logging.DEBUG, log_file="app.log"):
        """
        初始化日志器
        :param name: 日志器名称
        :param level: 日志级别
        :param log_file: 日志输出文件
        """
        # 创建logger对象
        self.logger = logging.getLogger(name)
        self.logger.setLevel(level)
        
        # 创建一个控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        
        # 创建一个文件处理器
        file_handler = logging.FileHandler(log_file)
        file_handler.setLevel(level)
        
        # 创建formatter并将其设置到处理器
        formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
        console_handler.setFormatter(formatter)
        file_handler.setFormatter(formatter)
        
        # 将处理器添加到logger
        self.logger.addHandler(console_handler)
        self.logger.addHandler(file_handler)
    
    def debug(self, message):
        """记录DEBUG级别日志"""
        self.logger.debug(message)
    
    def info(self, message):
        """记录INFO级别日志"""
        self.logger.info(message)
    
    def warning(self, message):
        """记录WARNING级别日志"""
        self.logger.warning(message)
    
    def error(self, message):
        """记录ERROR级别日志"""
        self.logger.error(message)
    
    def critical(self, message):
        """记录CRITICAL级别日志"""
        self.logger.critical(message)
    
# 测试自定义Log类
if __name__ == "__main__":
    log = Log(name="custom_logger", level=logging.DEBUG, log_file="custom_log.log")
    log.debug("这是一条调试日志")
    log.info("这是一条信息日志")
    log.warning("这是一条警告日志")
    log.error("这是一条错误日志")
    log.critical("这是一条严重错误日志")

这样一来,你以后想打日志,就只需要:

lua 复制代码
log.info("程序启动成功")
log.error("数据库连接失败")

是不是干净利落?


8. logging 的实战价值

说到这里,有人可能会问: "我只是写个小脚本,用 print 也没啥啊?"

没错,小脚本用 print 确实够了。

但是,一旦你进入 团队协作、线上项目、数据分析平台 这些场景,你就会发现:

  • 领导要看系统是否正常运行,得靠 INFO 日志。
  • 出问题时,开发要查 DEBUG 日志找原因。
  • 安全部门要追踪系统异常,得用 ERROR 和 CRITICAL 日志。

换句话说,logging 是 专业开发者的基本功,它不仅仅是"调试工具",更是"系统的眼睛"。


9. 小结:从 print 到 logging 的升级

今天我们学了:

  1. 为什么 print 不够用,logging 更优雅。
  2. logging 的基本用法和日志级别。
  3. 如何自定义日志格式,让输出更清晰。
  4. 如何把日志保存到文件,留"案底"。
  5. 用 handler + formatter 搭建复杂日志系统。
  6. 封装一个 Log 类,优雅复用。

如果说 print() 是自行车,那么 logging 就是汽车。 一开始可能需要学点"驾驶技巧",但一旦上手,速度、稳定性、安全性都不是一个量级。

所以,下次你再写 Python 代码的时候,别再傻乎乎用 print 满屏乱飞了。试试 logging,让调试优雅起来!

最后抛个问题: 👉 你现在项目里还在用 print 调试吗?还是已经切换到 logging 了?

欢迎在评论区聊聊,我想听听你的故事。

相关推荐
我是日安2 小时前
从零到一打造 Vue3 响应式系统 Day 4 - 核心概念:收集依赖、触发更新
前端·vue.js
ze_juejin2 小时前
JavaScript 中预防 XSS(跨站脚本攻击)
前端
我是天龙_绍2 小时前
🐴 记住了,节流(throttle)与防抖(debounce)
前端
凡二人2 小时前
Flip-js 优雅的处理元素结构变化的动画(解读)
前端·typescript
争当第一摸鱼前端2 小时前
Electron中的下载操作
前端
sjin2 小时前
React 源码 - Commit Phase 的工作细节
前端
FisherYu2 小时前
AI环境搭建pytorch+yolo8搭建
前端·计算机视觉
学前端搞口饭吃2 小时前
react reducx的使用
前端·react.js·前端框架
aidingni8882 小时前
掌握 JavaScript 中的 Map 和 Set
前端·javascript