Python Error Handling Patterns
LBYL checks a value before acting on it. EAFP acts first and catches the error if the act fails.
Look before you leap
LBYL checks the key first. The check and the use are two separate steps.
data = {"name": "Ada"}
if "name" in data:
print(data["name"])
else:
print("No name saved")Ask forgiveness instead
EAFP tries the lookup at once. The except block handles a missing key.
data = {"name": "Ada"}
try:
print(data["name"])
except KeyError:
print("No name saved")Catch one named error
This except names ValueError only. Any other error would still stop the program, as it should.
try:
age = int("twelve")
except ValueError:
print("Age must be a whole number")Log with context
A good failure note says what you were doing. Here the user number travels with the error.
user_id = 7
try:
int("seven")
except ValueError as err:
print(f"Loading user {user_id} failed: {err}")Example
import os
with open("score.txt", "w") as file:
file.write("42")
def load_lbyl(path):
if os.path.exists(path):
with open(path) as file:
return int(file.read())
return 0
def load_eafp(path):
try:
with open(path) as file:
return int(file.read())
except FileNotFoundError:
return 0
print(load_lbyl("score.txt"))
print(load_eafp("score.txt"))
print(load_eafp("missing.txt"))Key points
- LBYL: look before you leap — check first, then act
- EAFP: easier to ask forgiveness than permission — act first, then catch the error
- Use a specific except for each failure you expect, like KeyError or ValueError
- Log: write a note about a failure, with context values included
- Layer boundary: a place where one part of a program hands work to another part
- Fail fast at the edges, and translate errors in the middle layers
- Python code often uses EAFP.
In this example, the program first writes the number 42 into a file. The load_lbyl function checks that the file exists before opening it. The load_eafp function opens the file at once and catches FileNotFoundError. Both loaders return 42 for the real file. The EAFP loader also returns 0 for a missing file. The LBYL check has one weakness the EAFP version avoids. Another program could delete the file between the check and the open call. The EAFP version has no such gap, so its read is race-free.
Note
A bare except: catches everything, even KeyboardInterrupt, so always name the errors you expect.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
Which code is written in EAFP style?