Reputation: 387
I want to know what is the most elegant way of writing try
..except
statements in python. Assume I have this code:
with open(sys.argv[1]) as f:
for line in f:
try:
do_1(line)
except:
pass
try:
do_2(line)
except:
pass
try:
do_3(line)
except:
pass
...
...
What is the best way of writing this? My actions are sequential. However, if do_1
fails I still want to perform do_2
. If all of them are in one try
..except
block, then if do_1
fails, I will never reach do_2
. Is this the right way, or can I have one except
for all of d0_i
actions?
Upvotes: 2
Views: 11508
Reputation: 7035
Essentially, you need each do_<Step>
function to run inside the finally
block of the previous one, like so:
try:
do_1(line)
except:
# Handle failure
pass
finally:
# Run regardless
try:
do_2(line)
except:
# Handle failure
finally:
# Run regardless
try:
do_3(line)
...
This chains the functions together through the finally
block. Notice that in the event of an exception at any step, the exception is handled before starting the next step, which is guaranteed to run regardless of whether an exception is generated or not.
Since your functions all have the same shape (taking the same number and type of arguments), you can abstract out this pattern into a function, like tryChain
below:
def tryChain(functions, *sharedArgs)
f = functions.pop()
try:
f(*sharedArgs)
finally:
tryChain(functions)
try:
tryChain([do_1, do_2, ...], line, arg2, ...)
except SpecificException:
# Handle exception here, which may be propagated from any of the actions
pass
Note that in this case, only the last exception is thrown back to the caller; the others are hidden. (You could handle the exceptions inside tryChain
as well, with an except
block inserted there; or, you could pass in an error handler for each step; or a map from exception types to the appropriate handler, and re-throw the error if none of them matches — but at that point, you're practically reinventing exception handling.)
Upvotes: 0
Reputation: 59601
I would factor out the common code which is your try/except
statements. Something like:
def run_safely(f, *args):
try:
f(*args)
except SpecificException:
# handle appropriately here
pass
with open(sys.argv[1]) as f:
for line in f:
run_safely(do_1, line)
run_safely(do_2, line)
run_safely(do_3, line)
Upvotes: 7
Reputation: 280564
It's simple enough to write this as a loop:
for action in [do_1, do_2, do_3, ...]:
try:
action(line)
except AppropriateExceptionType:
pass
Upvotes: 9