Python Try Except

Tutorial 31 of 65 · pythondeck.com Python course

Exceptions are objects raised at runtime. Catch them with try/except, run cleanup in finally and run validation code in else (only if no exception occurred). Catch specific exception types, not bare except:.

Exceptions signal errors without crashing the whole program—if you handle them deliberately. Python's try/except/else/finally separates error handling, success-only logic, and cleanup. Catching broad exceptions hides bugs; catching specific types documents what you can recover from.

The EAFP style (Easier to Ask Forgiveness than Permission) tries an operation and handles failure—natural in Python for dict keys, file I/O, and parsing. LBYL (Look Before You Leap) checks preconditions first when checks are cheap and clear.

Exception hierarchy: inherit from Exception, not BaseException (except rare cases).

Catching specific types: ValueError, FileNotFoundError, KeyError.

else runs only if no exception was raised in the try block.

finally always runs—use for cleanup; prefer context managers when possible.

raise and raise ... from e for exception chaining.

Custom exception classes for domain errors (e.g. PaymentError).

Bare except: or except Exception: without re-raising swallows KeyboardInterrupt and SystemExit in some cases and masks stack traces. Log the full traceback with logging.exception before translating to user-facing messages.

Use else for code that should not run if the try failed—keeps the try block minimal. Context managers (with open(...)) often replace try/finally for resource cleanup.

In libraries, raise specific exceptions; in applications, catch at boundaries (CLI, HTTP handler) and convert to safe responses. Never expose internal tracebacks to end users in production.

Bare except: that catches everything including KeyboardInterrupt.

Empty except blocks that pass silently.

Using exceptions for normal control flow on hot paths (e.g. expected KeyError in tight loops).

Losing the original traceback by raising a new exception without from e.

Catching Exception around large code blocks instead of narrow operations.

Catch the narrowest exception type you can handle meaningfully.

Keep try blocks small; use else and finally intentionally.

Log with logging.exception at application boundaries; re-raise or wrap with context.

Define a small hierarchy of domain exceptions for your package's public API.

Re-read the examples below with these ideas in mind; change variable names and inputs to match your own project.

The program below demonstrates basic. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Example: Basic
# Run in the REPL or save as a .py file and execute with python.
try:
    x = int(input("n? "))
    print(10 / x)
except ValueError:
    print("not a number")
except ZeroDivisionError:
    print("can't divide by zero")

This sample walks through else / finally in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# Example: else / finally
# Run in the REPL or save as a .py file and execute with python.
try:
    f = open("out.json")
except FileNotFoundError:
    print("no file")
else:
    data = f.read()
    f.close()
    print(len(data), "chars")
finally:
    print("done")

Here is a hands-on illustration of raise + chain. Follow the inline comments first; only then execute the snippet and compare the result with what you expected.

# Example: Raise + chain
# Run in the REPL or save as a .py file and execute with python.
class AuthError(Exception): ...

try:
    raise ValueError("bad token")
except ValueError as e:
    raise AuthError("login failed") from e

The program below demonstrates specific except. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Catch the narrowest exception that you can handle
def parse_int(text):  # safe parser
    try:  # attempt conversion
        return int(text)  # may raise ValueError
    except ValueError:  # only handle bad int syntax
        return None  # signal failure to caller

print(parse_int("42"), parse_int("x"))  # 42 None
try:  # another pattern
    open("missing.txt")  # FileNotFoundError on missing path
except FileNotFoundError as err:  # bind exception object
    print("missing:", err.filename)  # structured detail
else:  # runs when no exception
    print("opened")  # not reached here

This sample walks through finally cleanup in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# finally always runs — ideal for releasing resources
def read_lines(path):  # generator with cleanup
    fh = open(path, encoding="utf-8")  # acquire handle
    try:  # read body
        for line in fh:  # stream lines
            yield line.rstrip()  # strip newline
    finally:  # guaranteed even on break/return
        fh.close()  # release OS handle

try:  # demonstrate raise path
    raise RuntimeError("boom")  # trigger except
except RuntimeError:  # handle
    print("handled")  # message
finally:  # still executes
    print("cleanup done")  # always prints

« Python PIP All tutorials Python User Input »