Exception handling is how you detect and recover from runtime errors using try / except / else / finally, instead of crashing the process.
try: code that might failexcept: handlers for specific exception types (prefer narrow types)else: runs if try had no exceptionfinally: always runs (cleanup)raise: throw / rethrow an exception
def parse_int(raw: str) -> int:
try:
value = int(raw)
except ValueError as exc:
raise ValueError(f"not an int: {raw!r}") from exc
else:
return value
finally:
print("attempt finished")
try:
print(parse_int("42"))
print(parse_int("x"))
except ValueError as exc:
print("handled:", exc)
# Catch multiple
try:
...
except (KeyError, IndexError) as exc:
...
# Bare except / except Exception: use sparingly; can hide bugsBest practices
- Catch the narrowest exception you can handle.
- Use
raise ... from excto preserve chains. - Prefer context managers for resource cleanup over only
finallyblocks when both apply. - Do not use exceptions for ordinary control flow in hot paths.