Douglas Douglas - 29 days ago 10
Python Question

Python shorthand exception handling

There's a certain problem I've been having with exception handling in Python. There have been many situations where there is an area of code where I want all exceptions to be ignored. Say I have 100 lines of code where I want this to happen.

This is what most would think would be the solution:

try:
line 1
line 2
line 3
...
line 99
line 100
except:
pass


This actually does not work in my situation (and many other situations). Assume line 3 has an exception. Once the exception is thrown, it goes straight to "pass", and skips lines 4-100. The only solution I've been able to come up with is this:

try:
line 1
except:
pass

try:
line 2
except:
pass

try:
line 3
except:
pass

...

try:
line 99
except:
pass

try:
line 100
except:
pass


But, as is obvious, this is extremely ugly, sloppy, and takes absolutely forever. How can I do the above code in a shorter, cleaner way? Bonus points if you give a method that allows "pass" to be replaced with other code.

Answer

As other answers have already stated, you should consider refactoring your code.

That said, I couldn't resist not hacking something together to be able to execute your function without failing and breaking out in case an exception occurs.

import ast, _ast, compiler

def fail():
    print "Hello, World!"
    raise Exception
    x = [4, 5]
    print x

if __name__ == '__main__':
    with open(__file__, 'r') as source:
        tree = ast.parse(source.read(), __file__)
        for node in ast.iter_child_nodes(tree):
            if isinstance(node, _ast.FunctionDef):
                _locals = {}
                for line in node.body:
                    mod = ast.Module()
                    mod.body = [line]
                    try:
                        exec(compile(mod, filename='<ast>', mode='exec'), _locals, globals())
                    except:
                        import traceback
                        traceback.print_exc()

The code executes any function it finds in global scope, and prevents it from exiting in the event it fails. It does so by iterating over the AST of the file, and creating a new module to execute for each line of the the function.

As you would expect, the output of the program is:

Hello, World!
Traceback (most recent call last):
  File "kek.py", line 18, in <module>
    exec(compile(m, filename='<ast>', mode='exec'), _locals, globals())
  File "<ast>", line 3, in <module>
Exception
[4, 5]

I should emphasize that using this in any production code is a bad idea. But for the sake of argument, something like this would work. You could even wrap it in a nice decorator, though that wouldn't do anything to the fact that it's a bad idea.

Happy refactoring!

Comments