diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3bc05f47b5d..f59bf136f3b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -565,7 +565,6 @@ peps/pep-0681.rst @jellezijlstra peps/pep-0682.rst peps/pep-0683.rst @ericsnowcurrently peps/pep-0684.rst @ericsnowcurrently -# peps/pep-0684.rst peps/pep-0685.rst @brettcannon peps/pep-0686.rst @methane peps/pep-0687.rst @encukou @erlend-aasland @@ -628,22 +627,23 @@ peps/pep-0746.rst @JelleZijlstra peps/pep-0747.rst @JelleZijlstra # ... peps/pep-0749.rst @JelleZijlstra -# ... peps/pep-0750.rst @gvanrossum @lysnikolaou peps/pep-0751.rst @brettcannon peps/pep-0752.rst @warsaw peps/pep-0753.rst @warsaw -# ... # peps/pep-0754.rst -# ... +peps/pep-0755.rst @warsaw peps/pep-0756.rst @vstinner peps/pep-0757.rst @vstinner +peps/pep-0758.rst @pablogsal @brettcannon peps/pep-0759.rst @warsaw +# ... peps/pep-0789.rst @njsmith # ... peps/pep-0801.rst @warsaw # ... peps/pep-2026.rst @hugovk +# ... peps/pep-3000.rst @gvanrossum peps/pep-3001.rst @birkenfeld # peps/pep-3002.rst diff --git a/peps/pep-0703.rst b/peps/pep-0703.rst index 0cc4e84145b..bed80c7842d 100644 --- a/peps/pep-0703.rst +++ b/peps/pep-0703.rst @@ -13,7 +13,7 @@ Post-History: `09-Jan-2023 `__, Resolution: https://discuss.python.org/t/pep-703-making-the-global-interpreter-lock-optional-in-cpython-acceptance/37075 .. note:: - The Steering Council accepts PEP 703, but with clear provisio: that + The Steering Council accepts PEP 703, but with clear proviso: that the rollout be gradual and break as little as possible, and that we can roll back any changes that turn out to be too disruptive – which includes potentially rolling back all of PEP 703 entirely if necessary diff --git a/peps/pep-0758.rst b/peps/pep-0758.rst new file mode 100644 index 00000000000..cffa85bb70e --- /dev/null +++ b/peps/pep-0758.rst @@ -0,0 +1,203 @@ +PEP: 758 +Title: Allow ``except`` and ``except*`` expressions without parentheses +Author: Pablo Galindo , Brett Cannon +PEP-Delegate: TBD +Status: Draft +Type: Standards Track +Created: 30-Sep-2024 +Python-Version: 3.14 + + +Abstract +======== + +This PEP [1]_ proposes to allow unparenthesized ``except`` and ``except*`` +blocks in Python's exception handling syntax. Currently, when catching multiple +exceptions, parentheses are required around the exception types. This was a +Python 2 remnant. This PEP suggests allowing the omission of these parentheses, +simplifying the syntax, making it more consistent with other parts of the syntax +that make parentheses optional, and improving readability in certain cases. + + +Motivation +========== + +The current syntax for catching multiple exceptions requires parentheses in the +``except`` expression (equivalently for the ``except*`` expression). For +example: + +.. code-block:: python + + try: + ... + except (ExceptionA, ExceptionB, ExceptionC): + ... + +While this syntax is clear and unambiguous, it can be seen as unnecessarily +verbose in some cases, especially when catching a large number of exceptions. By +allowing the omission of parentheses, we can simplify the syntax: + +.. code-block:: python + + try: + ... + except ExceptionA, ExceptionB, ExceptionC: + ... + +This change would bring the syntax more in line with other comma-separated lists +in Python, such as function arguments, generator expressions inside of a +function call, and tuple literals, where parentheses are optional. + +The same change would apply to ``except*`` expressions. For example: + +.. code-block:: python + + try: + ... + except* ExceptionA, ExceptionB, ExceptionC: + ... + +Both forms will also allow the use of the ``as`` clause to capture the exception +instance as before: + +.. code-block:: python + + try: + ... + except ExceptionA, ExceptionB, ExceptionC as e: + ... + + +Rationale +========= + +The decision to allow unparenthesized ``except`` blocks is based on the +following considerations: + +1. Simplicity: Removing the requirement for parentheses simplifies the syntax, + making it more consistent with other parts of the language. + +2. Readability: In cases where many exceptions are being caught, the removal of + parentheses can improve readability by reducing visual clutter. + +3. Consistency: This change makes the ``except`` clause more consistent with + other parts of Python where unambiguous, comma-separated lists don't require + parentheses. + +Specification +============= + +The syntax for the except clause will be modified to allow an unparenthesized +list of exception types. The grammar will be updated as follows: + +.. code-block:: peg + + except_block: + | 'except' expressions ['as' NAME] ':' block + | 'except' ':' block + + except_star_block + | 'except' '*' expressions ['as' NAME] ':' block + +This allows both the current parenthesized syntax and the new unparenthesized +syntax: + +.. code-block:: python + + try: + ... + except (ExceptionA, ExceptionB): # Still valid + ... + except ExceptionC, ExceptionD: # New syntax + ... + +The semantics of exception handling remain unchanged. The interpreter will catch +any of the listed exceptions, regardless of whether they are parenthesized or +not. + + +Backwards Compatibility +======================= + +This change is fully backwards compatible. All existing code using parenthesized +``except`` and ``except*`` blocks will continue to work without modification. +The new syntax is purely additive and does not break any existing code. + +It's worth noting that in Python 2 the unparenthesized syntax was allowed with +two elements, but had different semantics, in which the first element of the +list was used as the exception type and the second element as the capture +variable. This change does not reintroduce the Python 2 semantics, and the +unparenthesized syntax will behave identically to the parenthesized version. + + +Security Implications +===================== + +There are no known security implications for this change. The semantics of +exception handling remain the same, and this is purely a syntactic change. + + +How to Teach This +================= + +For new Python users, the unparenthesized syntax can be taught as the standard +way to catch multiple exceptions: + +.. code-block:: python + + try: + risky_operation() + except ValueError, TypeError, OSError: + handle_errors() + +For experienced users, it can be introduced as a new, optional syntax that can +be used interchangeably with the parenthesized version. Documentation should +note that both forms are equivalent: + +.. code-block:: python + + # These are equivalent: + except (ValueError, TypeError): + ... + + except ValueError, TypeError: + ... + +It should be emphasized that this is purely a syntactic change and does not +affect the behaviour of exception handling. + + +Reference Implementation +======================== + +A proof-of-concept implementation is available at +https://github.com/pablogsal/cpython/commits/notuples/. This implementation +modifies the Python parser to accept the new syntax and ensures that it behaves +identically to the parenthesized version. + + +Rejected Ideas +============== + +1. Allowing mixed parenthesized and unparenthesized syntax: + + .. code-block:: python + + try: + ... + except (ValueError, TypeError), OSError: + ... + + This was rejected due to the potential for confusion and to maintain a clear + distinction between the two styles. + +Footnotes +========= + +.. [1] Originally named "Parenthetically Speaking, We Don't Need 'Em" + +Copyright +========= + +This document is placed in the public domain or under the +CC0-1.0-Universal license, whichever is more permissive.