1. 什么是日志? #

用途 示例
调试 记录变量值、执行路径
监控 记录启动、连接、请求状态
审计 记录用户登录、数据修改
排错 记录异常堆栈,定位崩溃原因

2. 日志级别 #

级别 数值 何时使用
DEBUG 10 开发调试,详细内部信息
INFO 20 正常运行状态
WARNING 30 潜在问题,程序仍可运行
ERROR 40 功能出错
CRITICAL 50 严重错误,可能崩溃
# 导入 logging 模块
import logging

# 设置全局日志级别为 WARNING
logging.basicConfig(level=logging.WARNING)
# DEBUG 级别低于 WARNING,不会显示
logging.debug("不会显示")
# INFO 级别低于 WARNING,不会显示
logging.info("不会显示")
# WARNING 级别达标,会显示
logging.warning("会显示")
# ERROR 级别达标,会显示
logging.error("会显示")

3. 快速上手:basicConfig #

# 导入 logging 模块
import logging

# 一次性配置日志级别、格式和时间格式
logging.basicConfig(
    # 只记录 INFO 及以上级别
    level=logging.INFO,
    # 日志输出格式:时间 - 级别 - 消息
    format="%(asctime)s - %(levelname)s - %(message)s",
    # 时间戳格式
    datefmt="%Y-%m-%d %H:%M:%S",
)

# 记录正常运行信息
logging.info("程序启动")
# 记录潜在问题
logging.warning("内存使用率较高")
# 记录错误信息
logging.error("连接失败")

常用格式占位符:

占位符 含义
%(asctime)s 时间戳
%(levelname)s 级别名
%(name)s logger 名称
%(message)s 日志内容
%(filename)s 源文件名
%(lineno)d 行号

输出到文件:

# 配置日志输出到文件
logging.basicConfig(
    # 只记录 INFO 及以上级别
    level=logging.INFO,
    # 日志格式
    format="%(asctime)s - %(levelname)s - %(message)s",
    # 日志文件路径
    filename="app.log",
    # 追加模式写入
    filemode="a",
    # 使用 UTF-8 编码避免中文乱码
    encoding="utf-8",
)

4. 核心概念 #

logger.info("消息")
    → Logger 检查级别
    → Handler 用 Formatter 格式化
    → 输出到控制台/文件

5. 自定义 Logger #

# 导入 logging 模块
import logging

# 创建名为 my_app 的自定义 Logger
logger = logging.getLogger("my_app")
# 设置 Logger 最低记录级别为 DEBUG
logger.setLevel(logging.DEBUG)

# 创建控制台输出处理器
handler = logging.StreamHandler()
# 为处理器设置日志格式
handler.setFormatter(logging.Formatter(
    "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
))
# 将处理器添加到 Logger
logger.addHandler(handler)

# 记录程序启动信息
logger.info("程序启动")

6. 同时输出到控制台和文件 #

# 导入 logging 模块
import logging

# 创建自定义 Logger
logger = logging.getLogger("my_app")
# Logger 级别设为 DEBUG,允许所有级别通过
logger.setLevel(logging.DEBUG)

# 定义统一的日志格式
formatter = logging.Formatter(
    "%(asctime)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

# 创建控制台处理器
console = logging.StreamHandler()
# 控制台只显示 INFO 及以上
console.setLevel(logging.INFO)
# 应用统一格式
console.setFormatter(formatter)

# 创建文件处理器
file_handler = logging.FileHandler("app.log", encoding="utf-8")
# 文件记录 DEBUG 及以上的完整日志
file_handler.setLevel(logging.DEBUG)
# 应用统一格式
file_handler.setFormatter(formatter)

# 将控制台处理器添加到 Logger
logger.addHandler(console)
# 将文件处理器添加到 Logger
logger.addHandler(file_handler)

# DEBUG 级别低于控制台阈值,只在文件中可见
logger.debug("只在文件中可见")
# INFO 级别两个 Handler 均达标,两处都可见
logger.info("控制台和文件都可见")

7. 记录异常 #

# 导入 logging 模块
import logging

# 快速配置日志级别为 DEBUG
logging.basicConfig(level=logging.DEBUG)
# 获取当前模块的 Logger
logger = logging.getLogger(__name__)

# 定义除法函数
def divide(a, b):
    # 执行除法运算
    return a / b

# 捕获除零异常
try:
    # 触发 ZeroDivisionError
    divide(10, 0)
# 捕获所有异常
except Exception:
    # 自动记录异常堆栈跟踪
    logger.exception("除法运算出错")

8. 日志轮转 #

# 导入 logging 模块
import logging
# 导入按大小轮转的 Handler
from logging.handlers import RotatingFileHandler

# 创建自定义 Logger
logger = logging.getLogger("my_app")
# 设置最低记录级别
logger.setLevel(logging.DEBUG)

# 创建按大小轮转的文件处理器
handler = RotatingFileHandler(
    # 日志文件路径
    "app.log",
    # 单文件上限 10MB
    maxBytes=10 * 1024 * 1024,
    # 最多保留 5 个备份文件
    backupCount=5,
    # UTF-8 编码
    encoding="utf-8",
)
# 设置日志格式
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
# 将处理器添加到 Logger
logger.addHandler(handler)

9. 最佳实践与技巧 #

# 抑制第三方库 urllib3 的 DEBUG/INFO 日志
logging.getLogger("urllib3").setLevel(logging.WARNING)
# 抑制第三方库 requests 的 DEBUG/INFO 日志
logging.getLogger("requests").setLevel(logging.WARNING)
# 模块中的标准写法
# 导入 logging 模块
import logging
# 获取当前模块的 Logger(日志中显示模块路径)
logger = logging.getLogger(__name__)

# 定义用户服务类
class UserService:
    # 登录方法
    def login(self, username):
        # 记录用户登录操作
        logger.info(f"用户 {username} 登录")

10. 总结 #

10.1 速查 #

# 导入 logging 模块
import logging
# 获取当前模块的 Logger
logger = logging.getLogger(__name__)

# 记录调试信息(开发环境)
logger.debug("调试")
# 记录正常运行信息
logger.info("信息")
# 记录潜在问题
logger.warning("警告")
# 记录错误信息
logger.error("错误")
# 在 except 块中记录异常及堆栈
logger.exception("异常")

# 快速配置全局日志(小脚本适用)
logging.basicConfig(level=logging.INFO)

10.2 选型建议 #

场景 方案
学习/小脚本 basicConfig()
正式项目 自定义 Logger + 双 Handler
长期运行服务 加 RotatingFileHandler
记录崩溃 logger.exception()