on the importance of exceptions
Meredith Montgomery
mmontgomery at levado.to
Mon Sep 5 22:15:15 EDT 2022
Meredith Montgomery <mmontgomery at levado.to> writes:
> I'm trying to show people that exceptions are a very nice thing to have
> when it comes to detecting when something went awry somewhere. I'd like
> a real-world case, though.
Here's my contribution. I want to handle all errors in main() and the
real job is done in does_a_job(), which, in turns, needs to delegate
tasks to those other procedures that fail sometimes.
It's does_a_job() that /must/ distinguish the error codes because errors
come in as False from both opens_file() and reads_file(). So the checks
must be done both in does_a_job() and in main(). (We also notice that
does_a_job() has a return-type that's a union (sometimes an integer,
sometimes a string), which makes distinguishing error code and success a
bit harder.)
--8<---------------cut here---------------start------------->8---
from random import randint
def main():
r, data = does_a_job()
if r < 0:
if r == -1:
print("Fatal. Could not open file.")
return None
if r == -2:
print("Fatal. Could not read file")
return None
print(f"Great! We got the data: ``{r}''.")
def does_a_job():
okay = opens_file()
if not okay:
return -1
okay, data = reads_file()
if not okay:
return -2
closes_file()
return data
def open_file(): # Opens okay with probability 80%
return randint(1,10) <= 8
def read_file(): # Reads okay with probability 50%
return randint(1,10) <= 5, "data I am"
def closes_file(): # Works with probability 1
return True
--8<---------------cut here---------------end--------------->8---
If we could give the program a final destination at does_a_job(), the
job would be easier. But all we want to do in does_a_job() is to
propagate the error conditions upwards to main() to really decide what
to do. Exceptions lets us do that with a cleaner version.
--8<---------------cut here---------------start------------->8---
from random import randint
def main():
try:
data = does_a_job()
except FileNotFoundError:
print("Fatal. Could not open file.")
except MemoryError:
print("Fatal. Could not read file")
else:
print(f"Great! We got the data: ``{data}''.")
def does_a_job():
open_file()
data = reads_file()
close_file()
return data
def open_file(): # Opens okay with probability 80%
if randint(1,10) <= 8:
return True
raise FileNotFoundError("Sorry: the file system is /so/ busy right now.")
def reads_file(): # Reads okay with probability 50%
if randint(1,10) <= 5:
return "data I am"
raise MemoryError("Sorry: not enough memory for /all/ this data.")
def close_file(): # Works with probability 1
return True
--8<---------------cut here---------------end--------------->8---
More information about the Python-list
mailing list