本PEP为BaseException添加了一个可选的__timestamp_ns__属性,用于记录异常实例化的时间,且没有额外性能开销。当通过环境变量或命令行标志启用时,格式化的异常回溯会显示该时间戳。
随着异常组(PEP 654)的引入,Python程序可以同时传播多个不相关的异常。在调试这些异常,或将异常与外部日志和指标关联时,了解每个异常发生的时间通常与了解发生了什么同样重要。
考虑一个异步服务,它同时从多个后端获取数据并报告所有错误。结果的ExceptionGroup包含提交顺序的所有错误,但没有每个异常发生的时间指示。启用PYTHON_TRACEBACK_TIMESTAMPS=iso后,输出会为每个异常显示时间戳,便于分析发生顺序。
向BaseException添加一个新的读写属性__timestamp_ns__。它以C int64_t类型存储自Unix纪元以来的纳秒数(UTC)。当禁用时间戳、用于控制流异常或读取时钟失败时,该值为0。
复用的异常实例(如MemoryError)在分发时记录时间戳,而非原始分配时。
为避免影响正常控制流性能,即使功能启用,也不为StopIteration或StopAsyncIteration收集时间戳。这些异常在迭代过程中极高频触发。
通过CPython的标准机制启用:
PYTHON_TRACEBACK_TIMESTAMPS环境变量:设置为ns或1表示纳秒精度小数时间戳,iso表示ISO 8601 UTC格式-X traceback_timestamps=<format>命令行选项时间戳附加到异常回溯中的异常消息行,格式为<@timestamp>。仅影响格式化的回溯输出;str(exc)和repr(exc)不变。
TracebackException和公共格式化函数增加了timestamps关键字参数(默认为None),提供None(遵循全局配置)、False(从不显示)、True(显示任何非零值)三种行为。
提供新的工具函数traceback.strip_exc_timestamps(text),用于从格式化的回溯字符串中去除<@...>时间戳后缀。
添加新的doctest.IGNORE_EXCEPTION_TIMESTAMPS选项标志,使doctest在比较前去除实际输出中的时间戳。
时间戳存储为BaseException C结构中的单个int64_t字段。与使用异常备注(PEP 678)相比,结构字段在不填充时零成本,避免在抛出时创建字符串和列表对象,将所有格式化工作推迟到回溯渲染时。
实例化时间 vs. 抛出时间:在普遍常见的raise SomeError(...)形式中,两者相同。当不同时,实例化时间通常更有用:重新抛出保留了错误首次发生的时间。
性能测量:使用pyperformance套件测试,未观察到显著性能变化。仅对StopIteration/StopAsyncIteration的特殊处理在async_generators基准测试中显示约10%的性能提升。
该功能默认禁用,不影响现有异常处理代码。__timestamp_ns__属性始终可读,未收集时返回0。
当禁用时间戳时,异常以传统2元组格式(type, args)pickle。存在非零时间戳时,异常pickle为3元组格式(type, args, state_dict),其中__timestamp_ns__在状态字典中。
无。功能为选择加入且默认禁用。
__timestamp_ns__属性和配置选项将记录在异常模块参考、回溯模块参考和命令行界面文档中。这是一个高级功能,默认禁用,除非显式启用,否则不可见。不需要在入门材料中介绍。
CPython PR #129337。
Type: message行 vs. 回溯头行)感谢 Nathaniel J. Smith 提出原始想法,感谢 Daniel Colascione 在2025年对实现提供的初步审阅反馈。FINISHED
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。