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

Python 增强提案

PEP 758 – 允许 exceptexcept* 表达式不带括号

作者:
Pablo Galindo <pablogsal at python.org>, Brett Cannon <brett at python.org>
状态:
最终版
类型:
标准跟踪
创建日期:
2024年9月30日
Python 版本:
3.14
发布历史:
2024年10月2日
决议:
2025年3月14日

目录

重要

本PEP是一份历史文档。最新的、权威的文档现在可以在 The try statement 找到。

×

有关如何提出更改,请参阅 PEP 1

摘要

本PEP [1] 提议允许Python异常处理语法中的非括号式 exceptexcept* 块,但仅限于不使用 as 子句的情况。目前,当捕获多个异常时,异常类型周围需要括号。这是Python 2的遗留问题。本PEP建议允许省略这些括号,从而简化语法,使其与语法中其他可选括号的部分更加一致,并在某些情况下提高可读性。

动机

当前捕获多个异常的语法要求 except 表达式(以及 except* 表达式)中使用括号。例如:

try:
    ...
except (ExceptionA, ExceptionB, ExceptionC):
    ...

虽然这种语法清晰明确,但在某些情况下可能会被视为不必要的冗长,尤其是在捕获大量异常时。通过允许省略括号,我们可以简化语法:

try:
    ...
except ExceptionA, ExceptionB, ExceptionC:
    ...

这一改变将使语法更符合Python中其他逗号分隔的列表,例如函数参数、函数调用内的生成器表达式和元组字面量,这些地方括号是可选的。

同样的改变也适用于 except* 表达式。例如:

try:
    ...
except* ExceptionA, ExceptionB, ExceptionC:
    ...

当使用 as 子句捕获异常实例时,必须像以前一样使用括号。一些用户表示,不要求括号会让他们感到困惑,因为不清楚究竟是什么被分配给了目标,因为在语言的其他部分,可以在类似情况下使用多个 as 子句(例如在导入和上下文管理器中)。这意味着如果一个 as 子句被添加到前面的例子中,它必须这样做:

try:
    ...
except (ExceptionA, ExceptionB, ExceptionC) as e:
    ...

基本原理

允许非括号式 except 块的决定基于以下考虑:

  1. 简洁性:取消括号要求简化了语法,使其与语言的其他部分更加一致。
  2. 可读性:在捕获许多异常的情况下,取消括号可以通过减少视觉混乱来提高可读性。
  3. 一致性:这一改变使得 except 子句与Python中其他明确的、逗号分隔的列表(不要求括号)更加一致。

规范

except 子句的语法将被修改,以允许非括号式的异常类型列表。语法将更新如下:

except_block:
    | 'except' expressions ':' block
    | 'except' expression 'as' NAME ':' block
    | 'except' ':' block

except_star_block
    | 'except' '*' expressions ':' block
    | 'except' '*' expression 'as' NAME ':' block

这允许当前的括号式语法和新的非括号式语法,同时在使用 as 关键字时要求使用括号。

try:
    ...
except (ExceptionA, ExceptionB):  # Still valid
    ...
except ExceptionC, ExceptionD:    # New syntax
    ...
except (ExceptionE, ExceptionF) as e: # Parentheses still required
    ...

异常处理的语义保持不变。解释器将捕获列出的任何异常,无论它们是否带括号。

向后兼容性

此更改完全向后兼容。所有使用带括号的 exceptexcept* 块的现有代码将继续无需修改即可工作。新语法纯粹是添加性的,不会破坏任何现有代码。

值得注意的是,在Python 2中,非括号式语法允许有两个元素,但具有不同的语义,其中列表的第一个元素用作异常类型,第二个元素用作捕获变量。此更改不会重新引入Python 2的语义,非括号式语法的行为将与括号版本完全相同。

安全隐患

此更改没有已知的安全隐患。异常处理的语义保持不变,这纯粹是语法上的更改。

如何教授此内容

对于新的Python用户,可以将非括号式语法作为捕获多个异常的标准方式进行教学。

try:
    risky_operation()
except ValueError, TypeError, OSError:
    handle_errors()

对于有经验的用户,它可以作为一种新的可选语法引入,可以与括号版本互换使用。文档应指出两种形式是等效的。

# These are equivalent:
except (ValueError, TypeError):
    ...

except ValueError, TypeError:
    ...

应该强调的是,这纯粹是语法上的更改,不影响异常处理的行为。

参考实现

概念验证实现可在 https://github.com/pablogsal/cpython/commits/notuples/ 获取。此实现修改了Python解析器以接受新语法,并确保其行为与括号版本完全相同。

被拒绝的想法

  1. 允许混合括号式和非括号式语法
    try:
        ...
    except (ValueError, TypeError), OSError:
       ...
    

    由于可能造成混淆并为了保持两种风格之间的清晰区分,此提议被拒绝。

延迟的想法

  1. 在使用 as 关键字时允许非括号式表达式。我们决定推迟这种特定形式的原因是,目前没有明确的共识,双方都有合理的论据,最安全的做法是保持括号要求,因为如果用户发现这种不一致过于严重,可以在以后取消,而如果取消后用户认为这是个坏主意,则不容易再恢复。

脚注


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

最后修改:2025-05-26 23:00:11 GMT