Sometimes I need the following pattern within a for
loop. At times more than once in the same loop:
try:
# attempt to do something that may diversely fail
except Exception as e:
logging.error(e)
continue
Now I don't see a nice way to wrap this in a function as it can not return continue
:
def attempt(x):
try:
raise random.choice((ValueError, IndexError, TypeError))
except Exception as e:
logging.error(e)
# continue # syntax error: continue not properly in loop
# return continue # invalid syntax
return None # this sort of works
If I return None
than I could:
a = attempt('to do something that may diversely fail')
if not a:
continue
But I don't feel that does it the justice. I want to tell the for loop to continue
(or fake it) from within attempt
function.
Python already has a very nice construct for doing just this and it doesn't use continue
:
for i in range(10):
try:
r = 1.0 / (i % 2)
except Exception, e:
print(e)
else:
print(r)
I wouldn't nest any more than this, though, or your code will soon get very ugly.
In your case I would probably do something more like this as it is far easier to unit test the individual functions and flat is better than nested:
#!/usr/bin/env python
def something_that_may_raise(i):
return 1.0 / (i % 2)
def handle(e):
print("Exception: " + str(e))
def do_something_with(result):
print("No exception: " + str(result))
def wrap_process(i):
try:
result = something_that_may_raise(i)
except ZeroDivisionError, e:
handle(e)
except OverflowError, e:
handle(e) # Realistically, this will be a different handler...
else:
do_something_with(result)
for i in range(10):
wrap_process(i)
Remember to always catch specific exceptions. If you were not expecting a specific exception to be thrown, it is probably not safe to continue with your processing loop.
If you really don't want to handle the exceptions, which I still think is a bad idea, then catch all exceptions (except:
) and instead of handle(e)
, just pass
. At this point wrap_process()
will end, skipping the else:
-block where the real work is done, and you'll go to the next iteration of your for
-loop.
Bear in mind, Errors should never pass silently.