Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 473 – 为内置异常添加结构化数据

作者:
Sebastian Kreft <skreft at deezer.com>
状态:
已拒绝
类型:
标准跟踪
创建日期:
2014年3月29日
发布历史:

决议:
Python-Dev 消息

目录

摘要

AttributeErrorIndexErrorKeyErrorLookupErrorNameErrorTypeErrorValueError这样的异常,并没有提供程序员所需的所有信息来调试和更好地理解它们的原因。此外,在某些情况下,消息的格式甚至略有不同,这使得工具很难自动提供额外的信息来诊断问题。为了解决前者并为后者奠定基础,建议扩展这些异常,以便它们能够同时保存出错和受影响的实体。

基本原理

此PEP旨在解决的主要问题是,目前的错误消息不够具表现力,缺乏解决异常的一些关键信息。此外,错误消息中包含的信息格式并不总是相同的,这使得第三方库很难提供自动化的错误诊断。

例如,这些自动化工具可以检测拼写错误或显示/记录额外的调试信息。当运行测试或在长时间运行的应用程序中时,这些工具特别有用。

虽然理论上可以有这样的库,但它们需要诉诸于技巧来实现目标。一个例子是python-improved-exceptions [1],它修改字节码以保留对可能有趣的对象的引用,并解析错误消息以提取类型或名称等信息。不幸的是,这种方法极其脆弱且不可移植。

一个类似的提案 [2] 已为ImportError实现,并且以同样的方式,这个想法得到了支持 [3]。此外,近10年前Guido在 [11] 中要求有一个干净的API来访问像KeyErrorAttributeErrorNameErrorIndexError这样的异常中的受影响对象。在过去的一年里,也写了类似的议题和提案。还创建了一些其他议题,尽管得到了支持,但最终被放弃了。创建的议题的引用列在下面。

为了推动开发并集中信息和讨论,此PEP旨在成为一个元议题,总结上述所有讨论和想法。

示例

IndexError

错误消息没有引用列表的长度,也没有引用使用的索引。

a = [1, 2, 3, 4, 5]
a[5]
IndexError: list index out of range

KeyError

按照惯例,键是错误参数的第一个元素,但没有关于受影响字典的其他信息(键类型、大小等)。

b = {'foo': 1}
b['fo']
KeyError: 'fo'

AttributeError

对象的类型和出错的属性是错误消息的一部分。但是,存在一些不同的格式,并且信息并非总是可用。此外,尽管对象类型在某些情况下很有用,但考虑到Python的动态特性,拥有对象的引用本身将更有用。此外,类型的引用不是完全限定的,在某些情况下,类型过于通用,无法提供有用信息,例如在访问模块的属性时。

c = object()
c.foo
AttributeError: 'object' object has no attribute 'foo'

import string
string.foo
AttributeError: 'module' object has no attribute 'foo'

a = string.Formatter()
a.foo
AttributeError: 'Formatter' object has no attribute 'foo'

NameError

错误消息通常提供名称。

foo = 1
fo
NameError: global name 'fo' is not defined

其他情况

当目标对象是另一个表达式的结果时,问题会更难调试,例如

a[b[c[0]]]

这个问题也与以下事实有关:字节码只有行号信息而没有偏移量。这个提议在这种情况下会有帮助,但不如有偏移量那么有帮助。

提案

用以下内容扩展异常AttributeErrorIndexErrorKeyErrorLookupErrorNameErrorTypeErrorValueError

  • AttributeError: target w, attribute
  • IndexError: target w, key w, index (只是key的别名)
  • KeyError: target w, key w
  • LookupError: target w, key w
  • NameError: name, scope?
  • TypeError: unexpected_type
  • ValueError: unexpected_value w

带有上标w的属性可能需要是弱引用 [12] 以防止任何内存循环。然而,这可能会增加不必要的额外复杂性,正如R. David Murray [13] 所指出的。考虑到内置类型不支持弱引用,这一点尤其真实。

TODO(skreft): 用角落案例的例子来扩展这一点。

为了保持向后兼容性,这些新属性将是可选的,并且只能通过关键字参数传递。

建议添加此信息,而不仅仅是改进错误消息,因为前者将允许新的调试框架和工具,并且将来还可以切换到惰性生成的消息。消息生成已在 [2] 中讨论过,尽管它们目前尚未实现。它们不仅可以节省一些资源,还可以统一消息。

标准库将逐步更改,以便开始使用这些新属性。

潜在用途

例如,自动化工具可以搜索对象内的类似键,允许显示以下内容:

a = {'foo': 1}
a['fo']
KeyError: 'fo'. Did you mean 'foo'?

foo = 1
fo
NameError: global name 'fo' is not defined. Did you mean 'foo'?

有关TestRunner可能显示的输出,请参阅 [3]

性能

填充这些新属性只需要两个额外的参数,这些参数包含已有数据,因此影响应该是微不足道的。然而,对于KeyError可能需要特别注意,因为以下模式已经很普遍。

try:
  a[foo] = a[foo] + 1
except:
  a[foo] = 0

另外请注意,将这些对象存储在错误本身中将允许惰性生成错误消息,如 [2] 中讨论的。

参考资料


来源: https://github.com/python/peps/blob/main/peps/pep-0473.rst

最后修改: 2025-02-01 08:59:27 GMT