# Finally, You Can Drop the Parentheses in Python 3.14
> Python 3.14 simplifies exception handling with PEP 758, letting you drop parentheses when catching multiple exceptions, cleaner, consistent, and backward-safe.

Canonical: https://blog.abhimanyu-saharan.com/posts/finally-you-can-drop-the-parentheses-in-python-3-14
Published: 2025-05-25
Last updated: 2025-06-19
Authors: Abhimanyu Saharan
Categories: Python 3.14, Python

Python 3.14 introduces a subtle but meaningful enhancement in exception handling syntax through [PEP 758](https://peps.python.org/pep-0758/). 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.

```python
try:
    perform_operation()
except (IOError, ValueError, TimeoutError):
    handle_error()
```

Attempting to write:

```python
except IOError, ValueError:
    handle_error()
```

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:

```python
try:
    release_new_sleep_token_album()
except AlbumNotFound, SongsTooGoodToBeReleased:
    print("Sorry, no new album this year.")
```

This is equivalent to:

```python
try:
    release_new_sleep_token_album()
except (AlbumNotFound, SongsTooGoodToBeReleased):
    print("Sorry, no new album this year.")
```

Similarly, for exception groups using `except*`, which is used in conjunction with [PEP 654](https://peps.python.org/pep-0654/) for handling multiple concurrently raised exceptions:

```python
try:
    release_new_sleep_token_album()
except* AlbumNotFound, SongsTooGoodToBeReleased:
    print("Sorry, no new album this year.")
```

Again, this is equivalent to the traditional:

```python
except* (AlbumNotFound, SongsTooGoodToBeReleased):
    ...
```

> IMPORTANT
> 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:

```python
print("A", "B", "C")
for a, b in zip(x, y):
    ...
```

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:

```python
except ErrorA, ErrorB, ErrorC:
```

is visually less cluttered than:

```python
except (ErrorA, ErrorB, ErrorC):
```

### 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:

```python
try:
    risky_operation()
except (ConnectionError, TimeoutError) as e:
    log(e)
```

This remains **valid and required**:

```python
except ConnectionError, TimeoutError as e:  # ❌ SyntaxError
```

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` or `A 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.

## FAQ

### 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.
