try and except

Catching the errors you expect, letting through the ones you do not, and why a bare except is worse than no except at all.

try_except.py

try_except.py Python 3
Output

                    

bare_except.py

bare_except.py Python 3
Output

                    

Worth knowing

Catch the specific exception you expect: except ValueError:, not except:.
A bare except also swallows your typos, turning a crash into wrong output.
else runs when nothing raised. finally runs either way.
as e gives you the exception object, which carries the detail worth logging.

try and except: A Practical Guide

A try block runs code that might fail; an except block says what to do when a specific failure happens. The difficulty is not the syntax — it is being disciplined about which failures you actually catch.

The shape

try:
    return int(text)
except ValueError:
    return None

If int() raises ValueError, control jumps to the handler. If it raises anything else, the handler is skipped and the error keeps travelling up. That selectivity is the point.

Catch what you expect, nothing more

except:    # catches everything

This is almost always a mistake. It catches the error you were thinking of, and also your typos, your NameErrors, your AttributeErrors from a refactor you half-finished. The program stops crashing and starts producing wrong answers quietly, which is strictly worse: a crash tells you where to look.

The second program on this page has a deliberate typo inside a bare except. It returns 0, cheerfully, and nothing anywhere says a name was misspelled.

Name the exception:

except ValueError:
except (KeyError, IndexError):
except Exception as e:  # broad, but at least not BaseException

as e, and why you want it

except ValueError as e:
    print("could not convert:", e)

The exception object carries the detail — which key was missing, which value would not parse. Discarding it and printing "something went wrong" throws away the only part that would have helped.

else and finally

  • else runs when the try block raised nothing. It keeps the risky line alone in the try, so the handler cannot accidentally catch an error from the follow-up code.
  • finally runs either way, raised or not. It is where cleanup goes.

For files and locks, prefer with, which does the same job with less ceremony.

Raising your own

Handling is half of it. When a caller hands you something impossible, say so:

if age < 0:
    raise ValueError(f"age cannot be negative, got {age}")

Include the offending value in the message. "Invalid input" costs the next person a debugging session; "got -1" ends it immediately.

Ask forgiveness, not permission

Python leans toward trying the operation and handling the failure, rather than checking first. Checking if key in d before d[key] does the lookup twice and still has a gap between the check and the use. Try it and catch KeyError; it is faster in the common case and correct in all of them.

Check yourself

0 of 3

Answer without scrolling back up.

  1. Why is a bare `except:` discouraged?

  2. When does an `else` block on a try run?

  3. What does `as e` give you?

Cheat sheet

try and except

A try block runs code that might fail; an except block says what to do when a specific failure happens. The difficulty is not the syntax — it is being disciplined about which failures you actually catch.

PYTHON · vizlearn.in/python/try_and_except.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.