logging 模块记录 Python 日志,并讲解 Python 的 5 个日志级别、Python 错误处理和常见的 Python 错误类型。最后几节使用 logbrew-sdk 0.1.29 把同样的日志和崩溃发送到 LogBrew。所有示例都在 Python 3.13 上运行过,每个输出块都是真实输出。
Flask 应用请改用 Flask 日志。它会在同一套日志配置中加入请求链路。
写出第一条 Python 日志
把这个文件保存为app.py。在程序入口处调用一次 logging.basicConfig()。在每个模块中获取一个具名的记录器。
python3 app.py。输出会写到标准错误。
INFO,所以 debug 记录不会出现。logger.exception() 以 ERROR 级别记录日志,并附上回溯信息。只在 except 块中调用它。
像 "payment retry %d of %d", 2, 3 这样把值作为参数传入。只有当处理器接受这条记录时,Python 才会构建消息。每次重试的消息模板都相同,因此可以按模板搜索。
Python 日志级别
只有当记录的级别等于或高于记录器的级别时,记录器才会发送这条记录。处理器还可以设置一个更高的第二级别。
根记录器的默认级别是
WARNING。新记录器的级别是 NOTSET(0),并沿用父记录器的级别。在生产环境中设置 INFO,只在开发或短时诊断时使用 DEBUG。
记录器、处理器和格式器
- 记录器接收调用。使用
logging.getLogger(__name__),让记录器名称跟随模块路径。 - 处理器把记录发送到目标位置,例如终端、文件或 LogBrew。
- 格式器把记录转换为文本。
logging.NullHandler()。应用只配置一次处理器和级别。配置较多时,使用 logging.config.dictConfig()。
Python 错误处理
捕获你能处理的最具体的异常。只在成功时运行的代码放在else 中,始终要运行的代码放在 finally 中。用 raise ... from error 保留原始原因。
把这个文件保存为 orders.py。
- 只在处理异常的地方记录一次。不要在每一层都记录后再重新抛出,因为每一层都会多出一条重复记录。
- 不要写
except Exception: pass。如果要忽略某个错误,用WARNING或更高级别记录它,并写明原因。 - 捕获
Exception,而不是BaseException。BaseException还会捕获KeyboardInterrupt和SystemExit,而它们是有意停止程序的。 - 为调用方必须处理的错误定义自己的异常类,就像
OrderError这样。
报告多个错误
Python 3.11 及更高版本可以抛出ExceptionGroup。当一次检查发现多个错误时使用它。用 except* 分别处理每种类型。
常见的 Python 错误类型
程序可以处理的内置错误都继承自Exception。下表列出最常见的 Python 错误,以及每种错误应该先检查什么。
KeyboardInterrupt 和 SystemExit 继承自 BaseException,而不是 Exception。它们不是你代码中的错误。
把 Python 日志发送到 LogBrew
LogBrewLoggingHandler 是一个标准日志处理器。它会把接受的每条记录发送到 LogBrew。终端处理器保持不变。
1
创建项目密钥
2
安装 SDK
激活应用的虚拟环境,然后安装这个包。它需要 Python 3.10 或更高版本。
3
配置密钥和部署标识
4
添加处理器
把这个文件保存为
worker.py。在创建客户端之前调用 logging.basicConfig()。客户端会给根记录器添加一个处理器,而根记录器已有处理器时,basicConfig() 不会执行任何操作。HttpTransport() 在后台发送信号,时机是第一个信号产生 1 秒后,或累计到 50 个信号时。client.shutdown() 会发送剩余的信号并关闭客户端。5
运行程序
extra={...} 中的基本类型值会成为元数据。第二条日志的 exceptionName 为 KeyError,exceptionMessage 为 'seats'。要发送完整的回溯文本,创建处理器时传入 include_exception_text=True。6
读回日志
选择发送到 LogBrew 的记录
给处理器设置单独的级别,可以减少发送的记录。终端仍会收到INFO 及更高级别的记录。
把 Python 崩溃报告为问题
install_process_error_capture(client) 会报告脚本、worker 进程、启动代码和线程中未捕获的异常。每次崩溃都会成为 1 个问题,包含异常类型、消息、堆栈帧和异常链中的原因。Python 仍会像以前一样输出回溯信息并退出。
把这个文件保存为 startup.py 并运行。
FileNotFoundError,级别为 critical,机制为 python.excepthook。它的帧包含文件名、行号和函数,但不包含完整路径。线程中的崩溃级别为 error。Python 退出前,SDK 最多等待 2 秒完成发送。
故障排除
Web 应用参见 Flask 日志。要选择日志格式,参见结构化日志。其他运行时参见 SDK 接入。
