Finally, You Can Drop the Parentheses in Python 3.14
Python 3.14 introduces a subtle but meaningful enhancement in exception handling syntax through PEP 758. This change allows developers to omit parentheses when catching multiple exceptions in except
or except*
blocks, provided the as
clause is not used. This syntactic relaxation not only simplifies code but also aligns with Python's philosophy of readability and consistency.
Background: Exception Handling Syntax Before PEP 758¶
Traditionally, when catching multiple exceptions, Python required grouping them in a tuple using parentheses. This was not only a syntactic constraint but also a legacy of Python 2, where the comma operator behaved differently.
Attempting to write:
would result in a syntax error in Python 3, or worse, unintended behavior in Python 2.
Python 2 interpreted except IOError, ValueError:
as catching IOError
and assigning the exception instance to ValueError
, which was rarely what the developer intended.
What Does PEP 758 Change?¶
With Python 3.14, you can now write:
This is equivalent to:
Similarly, for exception groups using except*
, which is used in conjunction with PEP 654 for handling multiple concurrently raised exceptions:
Again, this is equivalent to the traditional:
This new unparenthesized form is only allowed when not using the
as
clause.
Why Was This Change Proposed?¶
1. Simplicity¶
Python favors readable, clean syntax. The requirement for parentheses in this specific context was inconsistent with other parts of the language where comma-separated expressions can be unparenthesized (e.g., function arguments).
2. Consistency¶
This aligns except
and except*
with constructs like:
In all such cases, parentheses are optional unless required by clarity or syntax.
3. Readability¶
For many developers, especially those scanning large blocks of try/except
clauses, removing the extra punctuation improves readability:
is visually less cluttered than:
4. Backward Compatibility¶
This change does not alter existing behavior or break existing code. The semantics remain the same.
Restrictions¶
Parentheses must still be used when an as
clause is present. This avoids ambiguity in assignment syntax:
This remains valid and required:
Why? Because Python has other contexts (e.g., import a as b, c as d
) where as
is applied to multiple items. Requiring parentheses preserves clarity:
except A, B as e:
is this(A, B) as e
orA as ?, B as e
? Hence, disallowed.
Specification and Grammar Changes¶
Python's grammar has been updated as follows:
except_block:
| 'except' expressions ':' block
| 'except' expression 'as' NAME ':' block
| 'except' ':' block
except_star_block:
| 'except' '*' expressions ':' block
| 'except' '*' expression 'as' NAME ':' block
Where expressions
is now allowed to be a comma-separated list without parentheses, provided the as
clause is not used.
Final Thoughts¶
PEP 758 is an example of Python evolving to be cleaner without breaking the past. It addresses a syntactic nitpick that, while minor, improves everyday usability and consistency.
This is not just about saving a pair of parentheses, it’s about removing artificial constraints that no longer serve a purpose. As with many things in Python, simplicity wins.
Python 3.14 is shaping up to be a release focused on ergonomic improvements, and PEP 758 is a clear step in that direction.
FAQs
What does PEP 758 change in Python 3.14?
PEP 758 allows developers to omit parentheses when catching multiple exceptions in except
and except*
clauses, as long as the as
clause is not used. This simplifies and clarifies exception syntax.
Why were parentheses required before this change?
Prior to Python 3.14, parentheses were required to group multiple exceptions due to legacy behavior from Python 2, where comma-separated exceptions had different semantics and could lead to ambiguous assignments.
Are there any restrictions to this new syntax?
Yes. Parentheses are still required when using an as
clause to bind the exception to a variable. This prevents ambiguity in expressions like except A, B as e:
which could be misinterpreted.
Does this change affect backward compatibility or existing code?
No. PEP 758 is fully backward compatible. Existing code using parentheses will continue to work, and removing them is optional unless the as
clause is present.
Why was this change made?
To improve readability, consistency, and simplicity in line with Python’s design philosophy. It aligns except
syntax with other constructs (like function calls or assignments) where parentheses are optional unless syntactically required.