I want to try a number of different approaches at the same task, catching exceptions each time an approach fails. I know the exception which will be raised if an attempt fails (and it can be different for each attempt). After the last attempt, I want to give up gracefully and move on.
I currently do this through nested try
/except
clauses:
try:
first_approach()
except Exception1:
try:
second_approach()
except Exception2:
try:
third_approach()
except:
give_up()
except Exception2:
try:
third_approach()
except:
give_up()
But this looks bad to me because third_approach()
is repeated. I can't see any help for this in the Python docs.
So how can I flatten this ugly nested code?
For example, imagine I am attempting to read a list of CSV files, without knowing their encoding in advance.
Some of the CSV files may even be XLS files posing as CSVs via their file extension.
I therefore want to try a few different encodings then, if none of those encodings work, try to read the file as excel.
for f in files:
try:
read_csv(f, encoding='utf-8')
except UnicodeDecodeError:
try:
read_csv(f, encoding='latin1')
except NotCsvError:
try:
read_excel(f)
except:
give_up()
except NotCsvError:
try:
read_excel(f)
except:
give_up()
You could loop over your approach-functions with a for
/else
loop.
The else
clause runs only if the for
is not terminated by the break
statement.
approaches = ((first_approach, [arg1, arg2, ...], {'kwarg1':kwarg1, 'kwarg2':kwarg2, ...}, (Approach1Exception1, Approach1Exception2, ...)),
(second_approach, ..., ..., ...),
(third_approach, ..., ..., ...),
...)
for approach, args, kwargs, exceptions in approaches:
try:
approach(*args, **kwargs)
break
except exceptions:
pass
else:
give_up()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With