try/except/else/finally, raising and chaining, custom hierarchies, cleanup helpers and the built-ins you meet daily.
d = {"a": 1}try:
n = int("x")
except ValueError as e:
print("bad number:", e)Catch one type; e is the exception object.
try:
d["z"] / 0
except (KeyError, ZeroDivisionError) as e:
print(type(e).__name__)Several types in one tuple.
try:
risky = 1 / 1
except ValueError:
print("value")
except Exception as e:
print("other:", e)
else:
print("no error")
finally:
print("always")else runs only without an exception; finally runs no matter what.
try:
int("x")
except Exception as e:
print(f"{type(e).__name__}: {e}")The generic catch; prefer specific types when you can act on them.
try:
{}["k"]
except KeyError:
passSilence one known case only — a bare except: also swallows Ctrl-C.
try:
int("x")
except ValueError as e:
e.args, str(e), repr(e)The message and its parts.
def age(n):
if n < 0:
raise ValueError(f"age must be >= 0, got {n}")
return nRaise a built-in with a message that includes the bad value.
try:
age(-1)
except ValueError:
print("logging, then re-raising")
raiseBare raise re-raises the current exception with its traceback.raises ValueError
try:
int("x")
except ValueError as e:
raise RuntimeError("config broken") from eChain: the original shows as 'The above exception was the direct cause'.raises RuntimeError
try:
int("x")
except ValueError:
raise RuntimeError("config broken") from Nonefrom None hides the original in the traceback.raises RuntimeError
assert len(d) == 1, "expected one key"AssertionError on False; stripped under python -O, so never for input validation.
e = ValueError("bad")
e.add_note("while parsing line 3")
e.__notes__Attach context that prints with the traceback (3.11+).
try:
raise SystemExit(2)
except SystemExit as e:
print("exit code", e.code)sys.exit(n) raises SystemExit(n); uncaught, the interpreter exits with that code.
class AppError(Exception):
"""Base for this app."""
class NotFound(AppError):
pass
class Invalid(AppError):
def __init__(self, field, msg):
super().__init__(f"{field}: {msg}")
self.field = fieldOne base class per project; callers catch AppError or a specific child.
try:
raise Invalid("email", "missing @")
except AppError as e:
print(e, e.field)A parent class catches every subclass.
isinstance(KeyError(), LookupError), issubclass(ZeroDivisionError, ArithmeticError)Built-ins form a tree too: catch the parent to cover siblings.
try:
raise RuntimeError("x") from ValueError("y")
except RuntimeError as e:
type(e.__cause__).__name____cause__ is the explicit chain; __context__ the implicit one.
from contextlib import suppress
with suppress(FileNotFoundError):
open("missing.txt")Ignore a specific exception without a try block.
from contextlib import contextmanager
@contextmanager
def tag(name):
print(f"<{name}>")
try:
yield
finally:
print(f"</{name}>")
with tag("b"):
print("bold")A generator-based context manager; finally is the __exit__.
import traceback
try:
int("x")
except ValueError:
text = traceback.format_exc()The full traceback as a string, for logs or error reports.
import logging
try:
int("x")
except ValueError:
logging.exception("parse failed")Logs at ERROR with the traceback attached; call it inside except.
import warnings
warnings.warn("old_api() is deprecated", DeprecationWarning, stacklevel=2)A warning, not an exception; shown once per location by default.
try:
import ujson as json
except ImportError:
import jsonOptional dependency fallback.
d.get("z", 0)KeyError → use .get, or in, or setdefault.
[1, 2][5] if len([1, 2]) > 5 else NoneIndexError → check the length, or slice (never raises).
try:
"a" + 1
except TypeError as e:
print(e)TypeError: wrong type for an operation → convert with str()/int().
try:
int("3.5")
except ValueError:
float("3.5")ValueError: right type, bad value.
try:
None.upper()
except AttributeError as e:
print(e)AttributeError: usually a None where you expected an object.
try:
open("nope.txt")
except FileNotFoundError as e:
print(e.filename)FileNotFoundError is an OSError; e.filename has the path.
it = iter([])
next(it, "empty")StopIteration: give next() a default.
try:
raise ExceptionGroup("batch", [ValueError("a"), TypeError("b")])
except* ValueError as eg:
print(len(eg.exceptions))except* handles groups of exceptions (3.11+); the unmatched TypeError re-raises as a group.raises ExceptionGroup
Want the topic explained, not just listed? The Errors & try/except lesson walks through it with graded exercises. Preparing for interviews? See the interview prep track.