Catch predictable failures with try/except/else/finally and raise your own exceptions to signal invalid data.
Open this lesson in KodokonA real program fails: missing file, invalid input, dropped network. Python signals these situations with exceptions, which interrupt execution and propagate up the call stack until a try/except catches them. The professional reflex: catch the most specific exception possible, as close as possible to where you know what to do.
def parse_age(text):
try:
return int(text)
except ValueError:
return None
print(parse_age("34")) # 34
print(parse_age("thirty")) # NoneThe full block has four branches. try contains the risky code, except handles the failure, else runs only if no exception was raised, and finally runs in every case - ideal for releasing a resource or logging. The point of else: keep the try minimal, so you can see at a glance which line can fail.
values = ["10", "abc", "25"]
total = 0
for value in values:
try:
number = int(value)
except ValueError:
print(f"Skip : {value}")
else:
total += number
finally:
print(f"Process : {value}")
print(total) # 35Your functions can also raise their own exceptions with raise, as soon as a piece of received data is invalid: better to fail immediately with a clear message than to produce a wrong result. Define a dedicated class inheriting from Exception: the caller will be able to catch it specifically, without accidentally intercepting other errors.
class EmptyCartError(Exception):
pass
def checkout(items):
if not items:
raise EmptyCartError("Empty cart.")
return round(sum(items), 2)
try:
print(checkout([]))
except EmptyCartError as error:
print(f"Error : {error}")