'On Error Resume Next in Python
Snippet 1
do_magic() # Throws exception, doesn't execute do_foo and do_bar
do_foo()
do_bar()
Snippet 2
try:
do_magic() # Doesn't throw exception, doesn't execute do_foo and do_bar
do_foo()
do_bar()
except:
pass
Snippet 3
try: do_magic(); except: pass
try: do_foo() ; except: pass
try: do_bar() ; except: pass
Is there a way to write code snippet 3 elegantly?
- if
do_magic()
fails or not,do_foo()
anddo_bar()
should be executed. - if
do_foo()
fails or not,do_bar()
should be executed.
In Basic/Visual Basic/VBS, there's a statement called On Error Resume Next
which does this.
Solution 1:[1]
In Python 3.4 onwards, you can use contextlib.suppress
:
from contextlib import suppress
with suppress(Exception): # or, better, a more specific error (or errors)
do_magic()
with suppress(Exception):
do_foo()
with suppress(Exception):
do_bar()
Alternatively, fuckit
.
Solution 2:[2]
If all three functions accept same number of parameters:
for f in (do_magic, do_foo, do_bar):
try:
f()
except:
pass
Otherwise, wrap the function call with lambda
.
for f in (do_magic, lambda: do_foo(arg1, arg2)):
try:
f()
except:
pass
Solution 3:[3]
If there are no parameters...
funcs = do_magic, do_foo, do_bar
for func in funcs:
try:
func()
except:
continue
Solution 4:[4]
If you are the one coding the fucntions, why not program the functions to return status codes? Then they will be atomic and you wont have to capture the error in the main section. You will also be able to perform roll back or alternate coding on failure.
def do_magic():
try:
#do something here
return 1
except:
return 0
in main program..
if do_magic() = 0:
#do something useful or not...
if do_foo() = 0:
#do something useful or not...
if do_bar() = 0:
#do something useful or not...
Solution 5:[5]
A lot of ident, but it works
try:
do_magic()
finally:
try:
do_foo()
finally:
try:
do_bar()
finally:
pass
Solution 6:[6]
you could try a nested ´try´ loop, alltho that might not be as elegantly pythonic as you might want. the ´lambda´ solution is is also a good way to go, did not mention because it was done in the previous answer
edit:
try:
do_magic()
finally:
try:
do_foo()
finally:
try:
do_bar()
except:
pass
edit 2:
well damnnit, this answer just got posted seconds beforehand again :|
Solution 7:[7]
In the question, Snippet 3 does not work but will work if you don't mind splitting each line over two lines...
try: do_magic()
except: pass
try: do_foo()
except: pass
try: do_bar()
except: pass
A working example..
import sys
a1 = "No_Arg1"
a2 = "No_Arg2"
a3 = "No_Arg3"
try: a1 = sys.argv[1]
except: pass
try: a2 = sys.argv[2]
except: pass
try: a3 = sys.argv[3]
except: pass
print a1, a2, a3
..if you save this to test.py and then at a CMD prompt in windows simply type test.py
it will return No_Arg1 No_Arg2 No_Arg3
because there were no arguments. However, if you supply some arguments, if type test.py 111 222
it will return 111 222 No_Arg3
etc.
(Tested - Windows 7, python2.7).
IMHO this is far more elegant than the nesting example replies. It also works exactly like On Error Resume Next and I use it when translating from VB6. One issue is that the try
lines cannot contain a conditional. I have found that as a rule, python cannot contain more than one :
in a line. That said, it simply means splitting the statement over 3 lines etc.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Aaron Christiansen |
Solution 2 | falsetru |
Solution 3 | Keith Aymar |
Solution 4 | Keith Aymar |
Solution 5 | xecgr |
Solution 6 | |
Solution 7 |