Lost Robot
Lost Robot

Reputation: 1321

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.

Upvotes: 3

Views: 1590

Answers (2)

Xyene
Xyene

Reputation: 2364

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!

Upvotes: 4

Aaranos
Aaranos

Reputation: 15

You could try breaking the code into smaller chunks so that it can properly handle errors instead of needing to abandon all progress and loop back through.

Another solution that can be used in addition to that is making checks, if set flags for your code to check if it can proceed or if it needs to repeat the last step you would be able to prevent extra iterations.

Example:

while not continue:
    try:
        a = input('Enter data')
    except:
        pass
    if a != null:
        continue = true

Upvotes: 0

Related Questions