Multiple try codes in one block - python

I have a problem with my code in the try block.
To make it easy this is my code:
try:
code a
code b #if b fails, it should ignore, and go to c.
code c #if c fails, go to d
code d
except:
pass
Is something like this possible?

You'll have to make this separate try blocks:
try:
code a
except ExplicitException:
pass
try:
code b
except ExplicitException:
try:
code c
except ExplicitException:
try:
code d
except ExplicitException:
pass
This assumes you want to run code c only if code b failed.
If you need to run code c regardless, you need to put the try blocks one after the other:
try:
code a
except ExplicitException:
pass
try:
code b
except ExplicitException:
pass
try:
code c
except ExplicitException:
pass
try:
code d
except ExplicitException:
pass
I'm using except ExplicitException here because it is never a good practice to blindly ignore all exceptions. You'll be ignoring MemoryError, KeyboardInterrupt and SystemExit as well otherwise, which you normally do not want to ignore or intercept without some kind of re-raise or conscious reason for handling those.

You can use fuckit module.
Wrap your code in a function with #fuckit decorator:
#fuckit
def func():
code a
code b #if b fails, it should ignore, and go to c.
code c #if c fails, go to d
code d

Extract (refactor) your statements. And use the magic of and and or to decide when to short-circuit.
def a():
try: # a code
except: pass # or raise
else: return True
def b():
try: # b code
except: pass # or raise
else: return True
def c():
try: # c code
except: pass # or raise
else: return True
def d():
try: # d code
except: pass # or raise
else: return True
def main():
try:
a() and b() or c() or d()
except:
pass

If you don't want to chain (a huge number of) try-except clauses, you may try your codes in a loop and break upon 1st success.
Example with codes which can be put into functions:
for code in (
lambda: a / b,
lambda: a / (b + 1),
lambda: a / (b + 2),
):
try: print(code())
except Exception as ev: continue
break
else:
print("it failed: %s" % ev)
Example with arbitrary codes (statements) directly in the current scope:
for i in 2, 1, 0:
try:
if i == 2: print(a / b)
elif i == 1: print(a / (b + 1))
elif i == 0: print(a / (b + 2))
break
except Exception as ev:
if i:
continue
print("it failed: %s" % ev)

Lets say each code is a function and its already written then the following can be used to iter through your coding list and exit the for-loop when a function is executed without error using the "break".
def a(): code a
def b(): code b
def c(): code c
def d(): code d
for func in [a, b, c, d]: # change list order to change execution order.
try:
func()
break
except Exception as err:
print (err)
continue
I used "Exception " here so you can see any error printed. Turn-off the print if you know what to expect and you're not caring (e.g. in case the code returns two or three list items (i,j = msg.split('.')).

You could try a for loop
for func,args,kwargs in zip([a,b,c,d],
[args_a,args_b,args_c,args_d],
[kw_a,kw_b,kw_c,kw_d]):
try:
func(*args, **kwargs)
break
except:
pass
This way you can loop as many functions as you want without making the code look ugly

I use a different way, with a new variable:
continue_execution = True
try:
command1
continue_execution = False
except:
pass
if continue_execution:
try:
command2
except:
command3
to add more commands you just have to add more expressions like this:
try:
commandn
continue_execution = False
except:
pass

I ran into this problem, but then it was doing the things in a loop which turned it into a simple case of issueing the continue command if successful. I think one could reuse that technique if not in a loop, at least in some cases:
while True:
try:
code_a
break
except:
pass
try:
code_b
break
except:
pass
etc
raise NothingSuccessfulError

Like Elazar suggested:
"I think a decorator would fit here."
# decorator
def test(func):
def inner(*args, **kwargs):
try:
func(*args, **kwargs)
except: pass
return inner
# code blocks as functions
#test
def code_a(x):
print(1/x)
#test
def code_b(x):
print(1/x)
#test
def code_c(x):
print(1/x)
#test
def code_d(x):
print(1/x)
# call functions
code_a(0)
code_b(1)
code_c(0)
code_c(4)
output:
1.0
0.25

Related

How to perform error handling for 200 functions?

Following is a sample function
def temp(data):
a = sample_function_1(data)
a = a[0][0]
b = sample_function_2(data,'no',0,30)
b = b[-1]
c = sample_function_3(data, 'thank', 0, None, 15, 5)
c = c[-2]
print(a, b, c)
return a, b, c
Error handling is done for sample_function_1, sample_function_2, and sample_function_3 . So the values returned by these functions cause no problem but the calculations done on the variables a, b, c can throw errors.
There are more than 200 functions like this and I need to manage the errors effectively. I know that try, catch, except is an option but are there any approaches that can be taken to solve this problem.
With 200 functions to change everything is going to be some hard work but you could try to use a decorator, you will only be able to intercept one error per function but it may be a good compromise for your case.
def exception_logger(func):
wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except IndexError:
...doSomething...
raise
return wrapper
#exception_logger
def temp(data):
...doSomething...
I think you can just define a function and just call the exception_logger function in any of your except block in any function.
import traceback
def exception_logger():
exception_log = traceback.format_exc().splitlines()
exception_log.append(str(datetime.now()))
print exception_log
return exception_log
def hello():
try:
print("Hello World!")
except Exception as e:
exception_logger()

How to best remove redundant calls from a code block, that should be executed when the block exists successfully?

I'm trying to simplify the following code (removing the redundant prints), but can't find a satisfying way to do this:
original code
def main():
if expression1:
print("1")
print("always_do_this")
return
if expression2:
print("2")
print("always_do_this")
return
# ... possibly more expressions and thus redundancy
print("always_do_this")
# do something else
My first idea was a try-(except-)else combination, but the else is not executed on a return in the try-block.
Solution 1 - extracting into a separate function
def func():
if expression1:
print("1")
return True
if expression2:
print("2")
return True
return False
def main():
result = func()
print("always_do_this")
if result:
return
# do something else
Solution 2 - workaround using finally
def main():
error = False
try:
if expression1:
print("1")
return
if expression2:
print("2")
return
except:
error = True
raise
finally:
if not error:
print("always_do_this")
# do something else
Surely there must be a better way to achieve this in python?
PS: Also any ideas for a better title would be appreciated...
PPS: I'm not directly asking about (subjective) codestyle, but wondering if there is a way to write this that I didn't consider (e.g. a language construct/pattern, that also makes the code more concise/cleaner; obviously there are a lot worse ways).
Check if your flow did not enter the first two if blocks by checking for the opposite of the first two if statements joined by an andso that you can execute "do something else" only if the first two if statements failed. Return at the end instead of in the middle of the if statements.
def main():
expression1 = True
expression2 = False
if expression1:
print("1")
elif expression2:
print("2")
print("always_do_this")
if not expression1 and not expression2:
# do something else
return
If the thing you always want to do is closing a file, I would use a with statement. In a more general case you can create your own context manager to have full control of what gets run at the end.
Sample code:
class my_closer:
def __enter__(self):
return True
def __exit__(self, type, value, traceback):
if type is None:
print("always_do_this")
else
print("An exception was raised: {}".format(type))
def main():
with my_closer() as c:
if someexpr:
print("1")
return
if someexpr:
print("2")
return
I added a superfluous else to print something about the exception in case of error, but leave it out to reproduce your original code more accurately.
This code is not shorter than yours with the trivial print statement, but I like this method for more complex "closer" code.
You can also define the context manager this way using the contextlib library:
from contextlib import contextmanager
#contextmanager
def my_closer(*args, **kwds):
try:
yield True
except:
#print("some error happened")
raise
else:
print("always_do_this")
References:
http://effbot.org/zone/python-with-statement.htm
https://docs.python.org/3/library/stdtypes.html#typecontextmanager
https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager

Python try/except depending on variable

i need continue in program after except when variable is True but when variable is False need exit program.
I think there will be if else but I'm not sure how to use it.
for examlpe:
var = True
try:
print 2/0
except:
exit(1)
... continue executing
var = False
try:
print 2/0
except:
exit(1)
... exit
Thanks for comments.
This ought to do the trick, by the way you should probably use raise.
var = True
try:
print 2/0
except:
if not var:
# I recommend using raise, as it would show you the error
exit(1)
If you have a number of except groups which will need to use the var try this
Note that you can expand myexcept using decorators or closures in order to set up additional processing within the exception as well. Since a function is an object, you can use a different specialfunc() for every except: that you write. You can set up the myexcept to handle calls to specialfunc() with arguments as well using the variable arguments process as shown below
def specialfunc1():
# put the special function code here
def specialfunc2(arg1):
# put the processing here
def specialfunc3(arg1, arg2):
# put the processing here
def myexcept(var, e, specialfunc, *args)
print 'Exception caught for ', e
if var:
specialfunc(*args)
else:
raise # This raises the current exception to force an exit
try:
# code you are testing
2/0
except Error1, e:
myexcept(var, e, specialfunc1)
except Error2, e:
myexcept(var, e, specialfunc2(arg1))
except Error3, e:
myexcept(var, e, specialfunc3(arg1, arg2))
except: # this default forces the regular exception handler
# remaining code

How to limit the number of failed attempts to call a function?

How rewrite this code in a pythonic way?
tried = 0
while tried < 3:
try:
function()
break
except Exception as e:
print e
tried += 1
Is there a built-in function I could use?
A more pythonic way to do something N times is to use xrange with the _ variable:
for _ in xrange(3):
try:
function()
break
except Exception as e:
print e
Also, consider catching a more specific exception instead of the root Exception class.
You can use a retry decorator:
#retries(3)
def execTask():
f()
One simpler than the one in the provided link could look like this:
def retry(times=3):
def do_retry(f, *args, **kwargs):
cnt = 0
while cnt < times:
try:
f(*args, **kwargs)
return
except:
cnt += 1
return do_retry
And could be used like this:
#retry(3)
def test():
print("Calling function")
raise Exception("Some exception")
tried = 0
while tried < 3:
try:
function()
break
except Exception as e:
print e
tried += 1
It's almost exactly how you wrote it, except you need a colon at the end of your while line and move the break to the "try" block.
Motivation
Given the motivation of the OP was to limit the number of failing attempt to run a function(), the following code does not provide any artificial gymnastics, but both limits the number of tries and retains the actual number of attempts for ex-post analyses ( if needed down the road )
tried = 0
while tried < 3:
try:
function() # may throw an Exception
break # on success pass through/return from function()
except Exception as e:
print e
tried += 1
# retains a value of tried for ex-post review(s) if needed

How to write multiple try statements in one block in python?

I want to do:
try:
do()
except:
do2()
except:
do3()
except:
do4()
If do() fails, execute do2(), if do2() fails too, exceute do3() and so on.
best Regards
If you really don't care about the exceptions, you could loop over cases until you succeed:
for fn in (do, do2, do3, do4):
try:
fn()
break
except:
continue
This at least avoids having to indent once for every case. If the different functions need different arguments you can use functools.partial to 'prime' them before the loop.
I'd write a quick wrapper function first() for this.
usage: value = first([f1, f2, f3, ..., fn], default='All failed')
#!/usr/bin/env
def first(flist, default=None):
""" Try each function in `flist` until one does not throw an exception, and
return the return value of that function. If all functions throw exceptions,
return `default`
Args:
flist - list of functions to try
default - value to return if all functions fail
Returns:
return value of first function that does not throw exception, or
`default` if all throw exceptions.
TODO: Also accept a list of (f, (exceptions)) tuples, where f is the
function as above and (exceptions) is a tuple of exceptions that f should
expect. This allows you to still re-raise unexpected exceptions.
"""
for f in flist:
try:
return f()
except:
continue
else:
return default
# Testing.
def f():
raise TypeError
def g():
raise IndexError
def h():
return 1
# We skip two exception-throwing functions and return value of the last.
assert first([f, g, h]) == 1
assert first([f, g, f], default='monty') == 'monty'
It seems like a really odd thing to want to do, but I would probably loop over the functions and break out when there were no exception raised:
for func in [do, do2, do3]:
try:
func()
except Exception:
pass
else:
break
Here is the simplest way I found, just embed the try under the previous except.
try:
do()
except:
try:
do2()
except:
do3()
You should specify the type of the exception you are trying to catch each time.
try:
do()
except TypeError: #for example first one - TypeError
do_2()
except KeyError: #for example second one - KeyError
do_3()
and so on.
if you want multiple try statments you can do it like this, including the except statement. Extract (refactor) your statements. And use the magic of and and or to decide when to short-circuit.
def a():
try: # a code
except: pass # or raise
else: return True
def b():
try: # b code
except: pass # or raise
else: return True
def c():
try: # c code
except: pass # or raise
else: return True
def d():
try: # d code
except: pass # or raise
else: return True
def main():
try:
a() and b() or c() or d()
except:
pass
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise

Categories

Resources