Skip to content
← All Python articles

Python explainer

Catch Several Exceptions Without Parentheses

About 3 min to read. Allow extra time to work through examples.

Python 3.14 lets you list several exception types in an except clause without parentheses. Learn when you still need them, and which old spelling now means something else.

This article uses Python. You can make it your practice mode to browse related content across the site.

Your function turns two spreadsheet cells into an average. Text that is not a number and a count of zero should both give 0.0. Python 3.14 lets you list both exception types without parentheses:

def average(total: str, count: int) -> float:
    try:
        return float(total) / count
    except ValueError, ZeroDivisionError:
        return 0.0


print(average("10", 4))    # 2.5
print(average("ten", 4))   # 0.0, from ValueError
print(average("10", 0))    # 0.0, from ZeroDivisionError

The handler catches either exception. Before 3.14 you had to write except (ValueError, ZeroDivisionError):. That form still works on every Python 3 version, with the same meaning.

This article and the three after it cover syntax added in Python 3.14 and 3.15. To run their examples, use Python 3.14 or newer, and 3.15 for the last two.

Keep the parentheses when you name the exception

To keep the exception in a variable with as, put the types in parentheses:

def average_or_reason(total: str, count: int) -> tuple[float, str]:
    try:
        return float(total) / count, ""
    except (ValueError, ZeroDivisionError) as exc:
        return 0.0, type(exc).__name__

Without the parentheses, Python 3.14 rejects the file:

SyntaxError: multiple exception types must be parenthesized when using 'as'

A single type needs no parentheses, so except ValueError as exc: is fine.

An old Python 2 line now means something else

In Python 2, except ValueError, e: caught a ValueError and stored it in e. You may still find that spelling in old code and old answers online. Python 3.13 and older reject it with a SyntaxError. Python 3.14 accepts it, and reads it as "catch ValueError or e", where e should be an exception type:

try:
    int("abc")
except ValueError, e:
    print("caught")

On Python 3.14 this never prints "caught". To check the handler, Python looks up the name e, finds nothing, and raises NameError: name 'e' is not defined. If no exception happens, Python never checks the handler, so the bug can hide until the first bad input. When you port such code, write except ValueError as e:.

Older versions cannot read the new spelling

On Python 3.12 and 3.13, a file that contains except ValueError, TypeError: fails to import with SyntaxError: multiple exception types must be parenthesized. A version check in the same file does not help, because Python reads the whole file before it runs any of it. The last article in this track, Write Code That Runs on Several Python Versions, shows what to do instead.

Check your understanding Your library supports Python 3.12 to 3.15. Should you switch its handlers to except A, B:? Show answer

No. Python 3.12 and 3.13 cannot parse that spelling, so the library would fail to import there. The parenthesized form means the same thing and works on every version you support. Even once your oldest version is 3.14, working handlers do not need a rewrite.

Check your understanding On Python 3.14, which is valid, except KeyError, IndexError: or except KeyError, IndexError as exc:? Show answer

Only the first. Without as, the parentheses are optional on 3.14. With as, you still need them, as in except (KeyError, IndexError) as exc:.

Going further

The change comes from PEP 758. It also covers except*, which handles exception groups, so except* ValueError, TypeError: is valid on 3.14. The new spelling changes only how a handler looks. It catches exactly the same exceptions as the parenthesized form.

step 18 of 23

Pattern Matching, f-Strings and Newer Syntax

Up next Escape HTML and Build SQL Parameters with t-Strings