You have a list of strings meant to be integers — but one of them is "oops". Calling int("oops") raises ValueError and stops your whole pipeline. How do you parse each value, return the integer when it works, and fall back to a default when it doesn't?
An if check? But how do I know in advance whether a string will parse?
You can't easily — there's no "is this parseable" function that covers every edge case. The Pythonic move is to try the operation and catch the exception. try/except lets you name the error you expect and handle it without crashing:
try:
return int(value)
except ValueError:
return defaultTry the risky operation inside try. If it raises ValueError, jump to except. If no error, the return in try fires and except is skipped entirely.
And I name the specific exception — ValueError — instead of a bare except?
Always name the exception you expect. Bare except catches everything including KeyboardInterrupt, which is almost never what you want. By being specific, you handle the known failure and let unknown errors bubble up:
def safe_parse_int(value: str, default: int) -> int:
try:
return int(value)
except ValueError:
return defaultWhat if the input is already an integer, like 42? Does int(42) work?
Yes — int() accepts ints, floats (truncates), and parseable strings. Only genuinely unparseable strings raise ValueError. So integers and numeric strings both return their int; non-numeric strings return the default.
So I can loop through a list of mixed strings and integers, call this for each one, and never crash — just get a clean list of ints with defaults filled in for the bad ones.
That's the whole payoff. try/except is what separates a pipeline that handles real data from one that crashes on the first surprise. Pair it with a comprehension — [safe_parse_int(v, 0) for v in raw] — and you have a resilient parse step in one line.
TL;DR: try: risky() / except SpecificError: fallback() — handle known failures without crashing.
except ValueError is specific; bare except is dangeroustry, fallback in exceptexcept (ValueError, TypeError) catches either| Operation | Raises |
|---|---|
int("abc") | ValueError |
dict["missing"] | KeyError |
10 / 0 | ZeroDivisionError |
[][0] | IndexError |
Match the exception class to the operation — never catch everything.
You have a list of strings meant to be integers — but one of them is "oops". Calling int("oops") raises ValueError and stops your whole pipeline. How do you parse each value, return the integer when it works, and fall back to a default when it doesn't?
An if check? But how do I know in advance whether a string will parse?
You can't easily — there's no "is this parseable" function that covers every edge case. The Pythonic move is to try the operation and catch the exception. try/except lets you name the error you expect and handle it without crashing:
try:
return int(value)
except ValueError:
return defaultTry the risky operation inside try. If it raises ValueError, jump to except. If no error, the return in try fires and except is skipped entirely.
And I name the specific exception — ValueError — instead of a bare except?
Always name the exception you expect. Bare except catches everything including KeyboardInterrupt, which is almost never what you want. By being specific, you handle the known failure and let unknown errors bubble up:
def safe_parse_int(value: str, default: int) -> int:
try:
return int(value)
except ValueError:
return defaultWhat if the input is already an integer, like 42? Does int(42) work?
Yes — int() accepts ints, floats (truncates), and parseable strings. Only genuinely unparseable strings raise ValueError. So integers and numeric strings both return their int; non-numeric strings return the default.
So I can loop through a list of mixed strings and integers, call this for each one, and never crash — just get a clean list of ints with defaults filled in for the bad ones.
That's the whole payoff. try/except is what separates a pipeline that handles real data from one that crashes on the first surprise. Pair it with a comprehension — [safe_parse_int(v, 0) for v in raw] — and you have a resilient parse step in one line.
TL;DR: try: risky() / except SpecificError: fallback() — handle known failures without crashing.
except ValueError is specific; bare except is dangeroustry, fallback in exceptexcept (ValueError, TypeError) catches either| Operation | Raises |
|---|---|
int("abc") | ValueError |
dict["missing"] | KeyError |
10 / 0 | ZeroDivisionError |
[][0] | IndexError |
Match the exception class to the operation — never catch everything.
Write `safe_parse_int(value, default)` that returns `int(value)` if the conversion succeeds, or `default` if `ValueError` is raised. Use try/except.
Tap each step for scaffolded hints.
No blank-editor panic.