Nick
Nick

Reputation: 387

writing multiple try and except in python

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

Answers (3)

jpaugh
jpaugh

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

Martin Konecny
Martin Konecny

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

user2357112
user2357112

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

Related Questions