Python Fundamentals contents
Exceptions
What runtime errors are, how to catch them with try / except / else / finally, and how to raise your own.
Read first: Functions
When Python cannot do what you asked, it raises an exception. If nothing handles it, the program stops and prints a traceback. On a judge that is a Runtime error verdict.
Common exceptions and their usual cause:
| Exception | Typical cause |
|---|---|
ValueError |
right type, wrong value: int("abc") |
TypeError |
wrong type: "a" + 1 |
IndexError |
list index out of range |
KeyError |
missing dictionary key |
ZeroDivisionError |
1 / 0 or n % 0 |
EOFError |
input() after the input ended |
RecursionError |
recursion too deep |
try / except
def to_int(text):
try:
return int(text)
except ValueError:
return None
assert to_int("42") == 42
assert to_int("4x2") is NoneCatch specific exceptions. A bare except: also swallows KeyboardInterrupt and hides real bugs.
Several handlers, and one handler for several types:
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return float("inf")
except (TypeError, ValueError) as err:
return f"bad input: {err}"
assert safe_divide(6, 3) == 2.0
assert safe_divide(1, 0) == float("inf")
assert safe_divide("a", 1).startswith("bad input")else and finally
elseruns if no exception occurred;finallyruns always, for cleanup.
log = []
def attempt(text):
try:
value = int(text)
except ValueError:
log.append("error")
else:
log.append(f"ok {value}")
finally:
log.append("done")
attempt("7")
attempt("x")
assert log == ["ok 7", "done", "error", "done"]The with statement from Files is the tidy way to guarantee cleanup.
Raising exceptions
Use raise to signal that a caller broke the rules of your function:
def sqrt_int(n):
if n < 0:
raise ValueError("n must be non-negative")
r = int(n ** 0.5)
while r * r > n:
r -= 1
while (r + 1) * (r + 1) <= n:
r += 1
return r
assert sqrt_int(99) == 9
try:
sqrt_int(-1)
except ValueError as err:
assert str(err) == "n must be non-negative"You can define your own exception type by subclassing Exception:
class InsufficientFunds(Exception):
pass
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFunds(f"need {amount - balance} more")
return balance - amount
try:
withdraw(10, 30)
except InsufficientFunds as err:
assert "20" in str(err)Reading until the input ends
A frequent judge idiom uses EOFError, although sys.stdin iteration is cleaner (see Files and Standard Input):
while True:
try:
line = input()
except EOFError:
break
print(line)Exercises
- Read a number from a string and print
invalidinstead of crashing when it is not numeric. - Write
get(lst, i, default)that returnslst[i]ordefaultwhen the index is out of range, usingtry. - Write a function that raises
ValueErrorif a password is shorter than 8 characters.