Python try/except examples

Catch the error you can actually handle, and keep the try block narrow enough to know which operation failed. The patterns below cover specific catches, cleanup, raising, retries, and the broad catch that makes programs fail silently.

🎙️ Published & recorded: ·

Specific errors and multiple handlers

Put only the operation expected to fail inside try. Catch ValueError when converting user text to a number. Bind the exception as e when its details help the user. Separate handlers when a timeout should retry but a lost connection should alert someone.

try:
    age = int(user_input)
except ValueError:
    print("that wasn't a number")

try:
    data = json.loads(text)
except json.JSONDecodeError as e:
    print(f"bad JSON at line {e.lineno}: {e.msg}")

try:
    resp = requests.get(url, timeout=5)
except requests.Timeout:
    retry()
except requests.ConnectionError:
    alert_ops()

except (ValueError, KeyError) as e:
    log(e)

A tuple of exception classes is right only when those failures receive identical handling. If the recovery differs, keep separate except clauses so the policy stays visible.

else and finally

Else runs only when try succeeded. It keeps later processing outside the protected block, so a bug in process is not mistaken for an open-file failure. Finally runs whether the operation succeeds, fails, or returns early, which makes it suitable for releasing locks and other unconditional cleanup.

try:
    f = open(path, encoding="utf-8")
except FileNotFoundError:
    print("no such file")
else:
    process(f.read())
    f.close()
finally:
    release_lock()

For files, a with statement is usually safer than manual close. Finally matters most when the resource has no context manager or when cleanup spans several operations.

Raise, re-raise, and retry

Raise ValueError when a caller supplied a value your function cannot accept. A bare raise inside except sends the same exception upward with its original traceback intact. For retries, catch only transient failures, wait longer after each failure, and re-raise after the final attempt.

def set_age(age):
    if age < 0:
        raise ValueError(f"age can't be negative, got {age}")

try:
    charge_card(order)
except PaymentError:
    log_incident(order)
    raise                          # same error and traceback

class QuotaExceeded(Exception):
    pass
for attempt in range(3):
    try:
        result = flaky_api_call()
        break
    except requests.Timeout:
        if attempt == 2:
            raise
        time.sleep(2 ** attempt)   # 1 second, then 2

Do not retry validation errors, permission failures, or a card decline. Repeating a permanent failure adds delay and can duplicate side effects. Retry policy belongs to the operation that knows whether another attempt is safe.

Fix silent catches and misleading tracebacks

The classic symptom is, my code runs but does nothing. Search for except colon pass or except Exception colon pass. Those lines discard the real traceback, including messages such as NameError: name user underscore id is not defined. Remove the catch while debugging, or log the traceback with logger dot exception.

NameError: name 'user_id' is not defined

try:
    save_user(user_id)
except Exception:
    pass                           # hides the NameError

# If a top-level worker truly must stay alive:
try:
    run_one_job()
except Exception:
    logger.exception("job failed")  # records full traceback
Concrete repair
Temporarily delete the broad handler and rerun to reveal the original traceback. Fix the named line. Then catch the narrow exception the program can recover from. At a process boundary where broad catching is intentional, use logger.exception(...); unlike logger.error(e), it includes the traceback.

A bare except is broader still: it also catches signals such as KeyboardInterrupt. Do not wrap a whole function to be safe. Let an error rise until some layer can make a real decision: retry, report it to the user, or stop.

📚 This is one page of our Python series. The full crash course (with audio for your commute): Python in 10 Minutes →

Tell me what missed

A correction is more useful than a compliment. This goes straight to the person who writes SwiftGrasp.

Was this page useful?
0/1000

Please do not include passwords, private keys, or personal information.