2

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?

1
  • You don't say anything about what's inside the do_X functions, so I'm going out on a limb here, but I have a feeling that maybe exceptions are not right in the first place. The pattern seems to be that you're trying several operations on each line (some kind of pattern matching?) and if there's an exception it's just swallowed anyway. Maybe use of return values could be a good choice? Exceptions are slow, so to write code where multiple exceptions are expected in a tight loop would result in slow code. Of course I don't know the details of the code, so I might be wrong for your case. Commented Jan 5, 2016 at 8:44

3 Answers 3

9

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
Sign up to request clarification or add additional context in comments.

1 Comment

@Nick You could create an anonymous function on the fly if necessary.
7

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)

1 Comment

One nitpick: The exception handling causes run_safely to need to operate at more than one level of abstraction at a tim. I.e, the caller of run_safely probably knows more about how to handle the exception than run_safely itself; but the exception is --- of necessity --- hidden from the caller.
0

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.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.