2026/4/5 12:36:28
网站建设
项目流程
做胃镜多少钱天津津门网站I,游戏推广网站如何做的,深圳专业网站排名公司,湖南移动官网网站建设Day 33#xff1a;【99天精通Python】日志记录 (Logging) - 告别 Print 调试
前言
欢迎来到第33天#xff01;
在之前的编程练习中#xff0c;当我们需要调试代码或者查看程序运行状态时#xff0c;最常用的办法就是 print()。
但是在真正的项目开发#xff08;尤其是服务…Day 33【99天精通Python】日志记录 (Logging) - 告别 Print 调试前言欢迎来到第33天在之前的编程练习中当我们需要调试代码或者查看程序运行状态时最常用的办法就是print()。但是在真正的项目开发尤其是服务器后台、长时间运行的任务中print有很多严重的缺点无法持久化关掉终端信息就没了。无法分级满屏的输出分不清哪些是重要的报错哪些只是普通的调试信息。缺少上下文不知道这条信息是几点几分、在哪个文件的哪一行打印的。Python 内置的logging模块提供了一套标准的日志记录系统。学会使用它是你的代码走向专业化的重要标志。本节内容为什么不用print日志的 5 个级别basicConfig快速配置日志格式化 (Formatter)进阶同时输出到控制台和文件实战练习打造一个生产级日志系统一、日志的 5 个级别 (Levels)logging模块定义了 5 个标准级别严重程度递增。我们可以根据需要选择记录哪个级别的信息。级别数值描述适用场景DEBUG10调试细节只有开发人员关心如变量的值、循环进度。INFO20正常信息确认程序按预期运行如服务启动、“任务开始”。WARNING30警告 (默认)出现意外但暂不影响运行如磁盘空间不足。ERROR40错误某个功能执行失败如文件未找到、“连接超时”。CRITICAL50严重错误程序可能崩溃无法继续运行。注意默认级别是WARNING。这意味着 DEBUG 和 INFO 级别的信息默认不会被打印出来。二、快速上手basicConfig2.1 最简单的用法importlogging# 默认只会打印 WARNING 及以上级别logging.debug(这是调试信息)# 不显示logging.info(这是普通信息)# 不显示logging.warning(这是警告信息)# 显示: WARNING:root:这是警告信息logging.error(这是错误信息)# 显示logging.critical(这是严重错误)# 显示2.2 配置日志 (保存到文件 修改级别)使用logging.basicConfig()可以对系统进行初始化设置。importlogging# 配置日志logging.basicConfig(filenameapp.log,# 指定输出文件 (如果不写默认输出到控制台)filemodea,# 模式: w覆盖, a追加 (默认是a)levellogging.INFO,# 设置最低显示级别为 INFOformat%(asctime)s - %(levelname)s - %(message)s,# 自定义格式encodingutf-8# 防止中文乱码 (Python 3.9))logging.info(程序启动了...)logging.warning(磁盘空间低于 10%)logging.error(数据库连接失败)运行后app.log文件内容2026-02-01 10:00:01,123 - INFO - 程序启动了... 2026-02-01 10:00:01,125 - WARNING - 磁盘空间低于 10% 2026-02-01 10:00:01,126 - ERROR - 数据库连接失败2.3 常用格式化字段在format参数中可以使用以下占位符%(asctime)s: 时间 (默认精确到毫秒)%(levelname)s: 日志级别名称 (INFO, ERROR…)%(message)s: 日志内容%(filename)s: 调用日志的文件名%(lineno)d: 代码行号%(threadName)s: 线程名三、进阶Logger, Handler, FormatterbasicConfig虽然简单但功能有限例如它很难实现同时输出到控制台和文件。Python 的 logging 系统采用了模块化设计由四大组件组成Logger (记录器)程序直接调用的接口。Handler (处理器)决定把日志发到哪里屏幕、文件、邮件…。Formatter (格式化器)决定日志长什么样。Filter (过滤器)决定哪些日志要输出较少用。实战同时输出到屏幕和文件这是开发中最常用的配置。importlogging# 1. 创建 Loggerloggerlogging.getLogger(MyProject)logger.setLevel(logging.DEBUG)# 设置全局最低级别# 2. 创建 Handlers# StreamHandler: 输出到控制台 (屏幕)console_handlerlogging.StreamHandler()console_handler.setLevel(logging.WARNING)# 屏幕只显示警告及以上# FileHandler: 输出到文件file_handlerlogging.FileHandler(app_detail.log,encodingutf-8)file_handler.setLevel(logging.DEBUG)# 文件记录所有细节# 3. 创建 Formattersfmt_simplelogging.Formatter(%(levelname)s: %(message)s)fmt_detaillogging.Formatter(%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s)# 4. 给 Handlers 绑定 Formatterconsole_handler.setFormatter(fmt_simple)file_handler.setFormatter(fmt_detail)# 5. 给 Logger 添加 Handlerslogger.addHandler(console_handler)logger.addHandler(file_handler)# --- 测试使用 ---logger.debug(这是一条调试信息 (只会进文件))logger.info(程序运行正常 (只会进文件))logger.warning(注意这里有个隐患 (屏幕文件))logger.error(出错了(屏幕文件))效果屏幕上只看到清爽的警告和错误信息。文件中记录了详尽的调试信息方便事后排查。四、捕获异常堆栈 (Traceback)当程序崩溃捕获异常时我们希望日志能记录下完整的报错堆栈信息而不仅仅是一句出错了。使用exc_infoTrue参数。try:1/0exceptZeroDivisionError:# 错误写法只记录了一句话不知道哪一行错# logging.error(除数不能为0)# 正确写法记录完整堆栈logging.error(发生了一个错误,exc_infoTrue)# 或者用更简单的写法 (仅在 except 块中有效)# logging.exception(发生了一个错误)日志输出ERROR:root:发生了一个错误 Traceback (most recent call last): File test.py, line 2, in module 1 / 0 ZeroDivisionError: division by zero五、日志轮转 (Rotating Logs)如果系统一直运行日志文件会越来越大最后把磁盘塞满。我们需要日志轮转比如每 10MB 切割一个新文件或者每天生成一个新文件。fromlogging.handlersimportRotatingFileHandler# 定义一个 10MB 大小的 handler最多保留 5 个备份# 当 log.txt 满了会重命名为 log.txt.1, log.txt.2 ...handlerRotatingFileHandler(app.log,maxBytes10*1024*1024,# 10MBbackupCount5,encodingutf-8)# 剩下的配置同上...六、小结日志系统 LoggingLogger (记录器)Handler (处理器)Formatter (格式化)Output (输出)StreamHandler (屏幕)FileHandler (文件)RotatingFileHandler (轮转)%(asctime)s%(levelname)s%(message)sConsoleapp.log关键要点别再用 Print 了除非是临时调试否则请使用 Logging。级别管理开发用 DEBUG/INFO生产环境用 WARNING/ERROR。异常记录在except块中用logging.exception()自动保存堆栈信息。模块化在不同的模块中使用logger logging.getLogger(__name__)获取独立的记录器。七、课后作业日志封装编写一个MyLogger类封装上述的屏幕文件双重输出逻辑。调用时只需要log MyLogger(test.log)然后log.info(...)即可。异常捕获器结合装饰器知识编写一个catch_error装饰器。如果被装饰的函数报错自动将错误堆栈写入日志文件而不是让程序崩溃。计算器升级将之前的计算器程序升级记录用户的每一次操作如 “User calculated 112”到calc.log文件中。下节预告Day 34单元测试 (Unittest)- 写好的代码怎么保证没 Bug靠人工点点点太慢了。明天我们学习如何编写自动化测试脚本让代码自己测自己系列导航上一篇Day 32 - 打包发布PyInstaller下一篇Day 34 - 单元测试Unittest待更新