日志编写(python)——Logging
🌟 第一步:先认识 logging 能做什么
想象你在写一个程序,你想知道:
- 程序什么时候启动/结束?
- 用户做了什么操作?
- 哪里出错了?为什么出错?
日志(logging)就是用来记录这些信息的工具,比 print() 更专业、更强大。
🔧 第二步:最最基础的用法(3 行代码)
import logging logging.warning("这是一个警告信息")运行结果(在终端):
WARNING:root:这是一个警告信息✅ 你看,不用配置,直接就能用!
但注意:
- 默认只显示 WARNING 及以上级别 的日志(INFO 和 DEBUG 不会显示)
- 默认输出到 控制台
- 日志格式是固定的:
级别:logger名:消息
📚 第三步:五大核心函数(按严重程度排序)
函数 | 用途 | 示例 |
| 调试细节(开发时用) |
|
| 一般信息 |
|
| 警告(可能有问题) |
|
| 错误(功能异常) |
|
| 严重错误(程序可能崩溃) |
|
💡 记住口诀:D-I-W-E-C(Debug → Critical,严重性递增)
⚙️ 第四步:如何让 INFO 和 DEBUG 也显示出来?
默认不显示它们,因为 logging 有一个 “最低级别” 设置。
方法:使用 basicConfig()
import logging # 必须在第一次调用 logging 之前配置! logging.basicConfig(level=logging.DEBUG) logging.debug("调试信息") # 会显示 logging.info("普通信息") # 会显示 logging.warning("警告") # 会显示输出:
DEBUG:root:调试信息 INFO:root:普通信息 WARNING:root:警告✅ level=logging.DEBUG 表示:显示 DEBUG 及以上所有级别
可选值:DEBUG, INFO, WARNING, ERROR, CRITICAL
🎨 第五步:自定义日志格式(Formatter)
默认格式太简单,我们想加上 时间、行号、函数名 等。
使用 format 参数:
import logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logging.info("程序开始运行")输出:
2026-01-14 13:30:45,123 - INFO - 程序开始运行常用格式占位符:
占位符 | 含义 |
| 时间(如 2026-01-14 13:30:45,123) |
| 日志级别(INFO/WARNING等) |
| 你写的日志内容 |
| logger 名称(默认是 "root") |
| 文件名 |
| 函数名 |
| 行号 |
更详细的例子:
format='%(asctime)s - %(name)s - %(funcName)s:%(lineno)d - %(levelname)s - %(message)s'输出:
2026-01-14 13:35:01,456 - root - <module>:10 - INFO - 用户登录💾 第六步:把日志写入文件(Handler)
光在控制台看不够,我们要保存到文件!
方法1:用 filename 参数(最简单)
import logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(message)s', filename='my_app.log' # ← 关键!日志写入文件 ) logging.info("这条日志会写入文件,不会显示在控制台")⚠️ 注意:加了 filename 后,默认不再输出到控制台!
方法2:同时输出到文件 + 控制台(推荐)
这时候就要用到 Handler 了(前面提过的四大组件之一)。
import logging # 创建 logger logger = logging.getLogger('my_logger') logger.setLevel(logging.DEBUG) # 创建两个 Handler console_handler = logging.StreamHandler() # 控制台 file_handler = logging.FileHandler('app.log') # 文件 # 设置格式 formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') console_handler.setFormatter(formatter) file_handler.setFormatter(formatter) # 把 Handler 加到 logger logger.addHandler(console_handler) logger.addHandler(file_handler) # 使用 logger.info("这条日志会同时出现在控制台和文件中!")✅ 这是企业项目中最常见的做法!
🔄 第七步:防止日志文件太大(日志轮转)
如果程序一直运行,日志文件会越来越大,最后撑爆硬盘!
解决方案:使用 RotatingFileHandler
import logging from logging.handlers import RotatingFileHandler logger = logging.getLogger('my_app') logger.setLevel(logging.INFO) # 创建轮转 handler:单个文件最大 1MB,保留 3 个备份 handler = RotatingFileHandler( 'app.log', maxBytes=1_000_000, # 1MB backupCount=3 # app.log.1, app.log.2, app.log.3 ) handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s')) logger.addHandler(handler) # 测试:写很多日志 for i in range(10000): logger.info(f"这是第 {i} 条日志")当 app.log 超过 1MB,系统会自动:
- 把
app.log改名为app.log.1 - 新建一个空的
app.log - 如果已有
app.log.3,就删除它(只保留3个)
🛠️ 第八步:记录异常(非常重要!)
当程序出错时,光说“出错了”没用,要看到 完整的错误堆栈。
错误做法:
try: 1 / 0 except Exception as e: logging.error("出错了:" + str(e)) # ❌ 只有错误信息,没有堆栈!正确做法(两种):
方法1:exc_info=True
try: 1 / 0 except Exception: logging.error("发生异常", exc_info=True) # ✅ 自动附带完整 traceback方法2:logger.exception()(仅在 except 块中用)
try: 1 / 0 except Exception: logging.exception("发生异常") # ✅ 等价于 error(..., exc_info=True)输出会包含:
ERROR:root:发生异常 Traceback (most recent call last): File "...", line 3, in <module> 1 / 0 ZeroDivisionError: division by zero🧩 第九步:每个模块用独立的 Logger(最佳实践)
在大项目中,不同模块(如数据库、API、任务调度)应该有独立的日志命名空间。
utils/db.py
import logging # 使用 __name__ 自动获得模块名:'utils.db' logger = logging.getLogger(__name__) def connect(): logger.info("正在连接数据库") # ...main.py
import logging from utils.db import connect # 配置一次即可 logging.basicConfig(level=logging.INFO) connect()输出:
INFO:utils.db:正在连接数据库✅ 好处:你可以单独控制某个模块的日志级别!比如只让 utils.db 显示 DEBUG,其他保持 INFO。
📝 总结:新手必须记住的 6 个要点
内容 | 说明 |
1. 用 ,别用 | 更专业、可配置、线程安全 |
2. 五大函数:debug/info/warning/error/critical | 按严重程度选择 |
3. 用 快速配置 | 但只能调用一次! |
4. 格式用 参数或 | 推荐包含时间、级别、消息 |
5. 写文件用 或 | 生产环境必须持久化日志 |
6. 记录异常用 或 | 否则看不到错误原因! |