I know that is a weird question, and probably there is not an answer.
I'm trying to execute the rest of the try block after an exception was caught and the except block was executed.
Example:
[...]
try:
do.this()
do.that()
[...]
except:
foo.bar()
[...]
do.this() raise an exception managed by foo.bar(), then I would like to execute the code from do.that(). I know that there is not a GOTO statement, but maybe some kind of hack or workaround!
Thanks!
A try... except... block catches one exception. That's what it's for. It executes the code inside the try, and if an exception is raised, handles it in the except. You can't raise multiple exceptions inside the try.
This is deliberate: the point of the construction is that you need explicitly to handle the exceptions that occur. Returning to the end of the try violates this, because then the except statement handles more than one thing.
You should do:
try:
do.this()
except FailError:
clean.up()
try:
do.that()
except FailError:
clean.up()
so that any exception you raise is handled explicitly.
Use a finally block? Am I missing something?
[...]
try:
do.this()
except:
foo.bar()
[...]
finally:
do.that()
[...]
If you always need to execute foo.bar() why not just move it after the try/except block? Or maybe even to a finally: block.
One possibility is to write a code in such a way that you can re-execute it all when the error condition has been solved, e.g.:
while 1:
try:
complex_operation()
except X:
solve_problem()
continue
break
fcts = [do.this, do.that]
for fct in fcts:
try:
fct()
except:
foo.bar()
You need two try blocks, one for each statement in your current try block.
This doesn't scale up well, but for smaller blocks of code you could use a classic finite-state-machine:
states = [do.this, do.that]
state = 0
while state < len(states):
try:
states[state]()
except:
foo.bar()
state += 1
Here's another alternative. Handle the error condition with a callback, so that after fixing the problem you can continue. The callback would basically contain exactly the same code you would put in the except block.
As a silly example, let's say that the exception you want to handle is a missing file, and that you have a way to deal with that problem (a default file or whatever). fileRetriever is the callback that knows how to deal with the problem. Then you would write:
def myOp(fileRetriever):
f = acquireFile()
if not f:
f = fileRetriever()
# continue with your stuff...
f2 = acquireAnotherFile()
if not f2:
f2 = fileRetriever()
# more stuff...
myOp(magicalCallback)
Note: I've never seen this design used in practice, but in specific situations I guess it might be usable.
Related
I want to know what is the most elegant way of writing try..except statements in python. Assume I have this code:
with open(sys.argv[1]) as f:
for line in f:
try:
do_1(line)
except:
pass
try:
do_2(line)
except:
pass
try:
do_3(line)
except:
pass
...
...
What is the best way of writing this? My actions are sequential. However, if do_1 fails I still want to perform do_2. If all of them are in one try..except block, then if do_1 fails, I will never reach do_2. Is this the right way, or can I have one except for all of d0_i actions?
It's simple enough to write this as a loop:
for action in [do_1, do_2, do_3, ...]:
try:
action(line)
except AppropriateExceptionType:
pass
I would factor out the common code which is your try/except statements. Something like:
def run_safely(f, *args):
try:
f(*args)
except SpecificException:
# handle appropriately here
pass
with open(sys.argv[1]) as f:
for line in f:
run_safely(do_1, line)
run_safely(do_2, line)
run_safely(do_3, line)
Essentially, you need each do_<Step> function to run inside the finally block of the previous one, like so:
try:
do_1(line)
except:
# Handle failure
pass
finally:
# Run regardless
try:
do_2(line)
except:
# Handle failure
finally:
# Run regardless
try:
do_3(line)
...
This chains the functions together through the finally block. Notice that in the event of an exception at any step, the exception is handled before starting the next step, which is guaranteed to run regardless of whether an exception is generated or not.
Since your functions all have the same shape (taking the same number and type of arguments), you can abstract out this pattern into a function, like tryChain below:
def tryChain(functions, *sharedArgs)
f = functions.pop()
try:
f(*sharedArgs)
finally:
tryChain(functions)
try:
tryChain([do_1, do_2, ...], line, arg2, ...)
except SpecificException:
# Handle exception here, which may be propagated from any of the actions
pass
Note that in this case, only the last exception is thrown back to the caller; the others are hidden. (You could handle the exceptions inside tryChain as well, with an except block inserted there; or, you could pass in an error handler for each step; or a map from exception types to the appropriate handler, and re-throw the error if none of them matches — but at that point, you're practically reinventing exception handling.)
I have some code which represents a test case within a proprietary testing framework that looks something like this:
def test_alarm(self):
self.setup_some_test_data()
try:
self.send_alarm_message()
except:
print "Unexpected error:", sys.exc_info()
finally:
self.teardown_some_test_data()
I've been told to drop the print as it's not necessary and the test framework will in any case catch any exceptions, which is preferred to catching them here, but I still need to always clear the data down, as in the finally block.
Do I just drop the except block entirely? Alternatively, how, can I structure the code to effectively have an empty except block and retain the finally? Is this good practice in Python or is there a better way to do it?
Edit Note that I did try just dropping the except block entirely, and I had no obvious run-time problems, though since exceptions are unlikely in the the call to send_alarm_message(), it was unclear to me how it would work if an exception was thrown or whether this was considered good practice by the Python community.
Either drop the except Block, or improove it really by adding
except [Exception-Class]:
pass
where [Exception-Class] is the exception to be excepted. This adds some sugar on it, because really unexpected Errors are not getting catched by this. (Or add this as a seperate:
except Exception, ex:
print "Unexpected error:", ex
Yes, you can drop the except block completely, it is a valid python syntax to have just try and finally . Example -
In [58]: try:
....: print("Blah")
....: finally:
....: print("halB")
....:
Blah
halB
Please note this will not catch any Exceptions/Errors that occur within the try block, and I am guessing that is what you want.
I have seen this used at quite some places, where we are creating some variables/resources that need to be cleared irrespective of whether any exceptions/errors occur, but we do not want to handle any Exceptions at that particular place.
If you don't want to do anything in except block, then you can pass it.
try:
self.send_alarm_message()
except:
pass
finally:
self.teardown_some_test_data()
I have two objectives with this try/except statement.
It needs to return a value of 1 if no problems occurred, or 0 if any problems occurred.
It needs to raise an exception and end the script.
I have the return value working. I also have the SystemExit() working. But together, they aren't working.
My Python Script (that's relevant):
except IOError:
value_to_return = 0
return value_to_return
raise SystemExit("FOOBAR")
With this, it ignores the raise SystemExit("FOOBAR") line completely. How do I go about getting a returned value and still raise SystemExit("FOOBAR")? This may be elementary to some, but I'm actually having quite a bit of difficulty with it.
Returning and raising are mutually exclusive.
Raising SystemExit will end the script. A few cleanup routines get to run, and if the caller really, really wants to, they can catch the SystemExit and cancel it, but mostly, you can think of it as stopping execution right there. The caller will never get a chance to see a return value or do anything meaningful with it.
Returning means you want the script to continue. Continuing might mean having the caller raise SystemExit, or it might mean ignoring the error, or it might mean something else. Whatever it means is up to you, as you're the one writing the code.
Finally, are you sure you should be handling this error at all? Catching an exception only to turn it into a system shutdown may not be the most useful behavior. It's not a user-friendly way to deal with problems, and it hides all the useful debugging information you'd get from a stack trace.
You can raise an error with a 'returning_value' argument to be used after the calling.
Another pythonic answer to your problem could be to make use of the error arguments in the raise and then, in your call manage the error to get the value, convert it from string and get your 'return-ish'.
def your_f():
try:
some_io_thingy_ok()
return 1
except IOError:
raise SystemExit("FOOBAR", 0)
try:
my_returning_value = your_f()
except SystemExit as err:
my_returning_value = err.args[1]
print(my_returning_value)
From Python 3 docs :
When an exception occurs, it may have an associated value, also known
as the exception’s argument. The presence and type of the argument
depend on the exception type.
The except clause may specify a variable after the exception name. The
variable is bound to an exception instance with the arguments stored
in instance.args. For convenience, the exception instance defines
str() so the arguments can be printed directly without having to reference .args. One may also instantiate an exception first before
raising it and add any attributes to it as desired.
To exit a script and return an exit status, use sys.exit():
import sys
sys.exit(value_to_return)
I think what you may be looking for is something more like this:
def some_function():
# this function should probably do some stuff, then return 1 if
# it was successful or 0 otherwise.
pass
def calling_function():
a = some_function()
if a == 1:
raise SystemExit('Get the heck outta here!')
else:
# Everything worked!
pass
You can't "raise" and "return" in the same time, so you have to add a special variable to the return value (e.g: in tuple) in case of error.
E.g:
I have a function (named "func") which counts something and I need the (partial) result even if an exception happened during the counting. In my example I will use KeyboardInterrupt exception (the user pressed CTRL-C).
Without exception handling in the function (it's wrong, in case of any exception the function doesn't give back anything):
def func():
s=0
for i in range(10):
s=s+1
time.sleep(0.1)
return s
x=0
try:
for i in range(10):
s=func()
x=x+s
except KeyboardInterrupt:
print(x)
else:
print(x)
And now I introduce a boolean return value (in a tuple, next to the original return value) to indicate if an exception happened. Because in the function I handle only the KeyboardInterrupt exception, I can be sure that's happened, so I can raise the same where I called the function:
def func():
try:
s=0
for i in range(10):
s=s+1
time.sleep(0.1)
except KeyboardInterrupt: # <- the trick is here
return s, True # <- the trick is here
return s, False # <- the trick is here
x=0
try:
for i in range(10):
s,e=func()
x=x+s
if e: # <- and here
raise KeyboardInterrupt # <- and here
except KeyboardInterrupt:
print(x)
else:
print(x)
Note: my example is python3. The time module is used (in both code above), but I haven't import it just to make it shorter. If you want to really try it, put at the beginning:
import time
i was looking for an answer without using try, use 'finally' keyword like this.. if any one knows fill me in
here is an answer for your poblem
try:
9/0#sample error "don't know how to make IOError"
except ZeroDivisionError:
value_to_return = 0
raise SystemExit("FOOBAR")
finally:return value_to_return
I am learning Python and have stumbled upon a concept I can't readily digest: the optional else block within the try construct.
According to the documentation:
The try ... except statement has an optional else clause, which, when
present, must follow all except clauses. It is useful for code that
must be executed if the try clause does not raise an exception.
What I am confused about is why have the code that must be executed if the try clause does not raise an exception within the try construct -- why not simply have it follow the try/except at the same indentation level? I think it would simplify the options for exception handling. Or another way to ask would be what the code that is in the else block would do that would not be done if it were simply following the try statement, independent of it. Maybe I am missing something, do enlighten me.
This question is somewhat similar to this one but I could not find there what I am looking for.
The else block is only executed if the code in the try doesn't raise an exception; if you put the code outside of the else block, it'd happen regardless of exceptions. Also, it happens before the finally, which is generally important.
This is generally useful when you have a brief setup or verification section that may error, followed by a block where you use the resources you set up in which you don't want to hide errors. You can't put the code in the try because errors may go to except clauses when you want them to propagate. You can't put it outside of the construct, because the resources definitely aren't available there, either because setup failed or because the finally tore everything down. Thus, you have an else block.
One use case can be to prevent users from defining a flag variable to check whether any exception was raised or not(as we do in for-else loop).
A simple example:
lis = range(100)
ind = 50
try:
lis[ind]
except:
pass
else:
#Run this statement only if the exception was not raised
print "The index was okay:",ind
ind = 101
try:
lis[ind]
except:
pass
print "The index was okay:",ind # this gets executes regardless of the exception
# This one is similar to the first example, but a `flag` variable
# is required to check whether the exception was raised or not.
ind = 10
try:
print lis[ind]
flag = True
except:
pass
if flag:
print "The index was okay:",ind
Output:
The index was okay: 50
The index was okay: 101
The index was okay: 10
import sys
def checkarg():
try:
filename=str(sys.argv[1])
if filename=="-mycommand":
print "SPECIFIC_TEXT"
sys.exit()
else:
return filename
except:
print "ERROR"
sys.exit()
Hello all...i have a problem with the code above. When i call the 'checkarg' function, if i did not pass any parameter on the command line i have the "ERROR" output and sys exit, just as expected.
But, if i provide a parameter on the command line (like "-mycommand") it prints the "SPECIFIC_TEXT" and then prints "ERROR" message from the EXCEPT block too.
The TRY block will only run when I provide a parameter, if I don't, then EXCEPT will get the turn. But, it is running the TRY and EXCEPT blocks together.
Does anybody knows the reason of this behavior?? Any mistake on my code? Tks for all !
I think I understand your question...
sys.exit() exits by raising a SystemExit exception, which your except statement is catching.
Answer found here: http://docs.python.org/library/sys.html
sys.exit([arg])
Exit from Python. This is implemented by raising the SystemExit exception, so cleanup actions specified by finally clauses of try statements are honored, and it is possible to intercept the exit attempt at an outer level.
sys.exit works by raising an exception. That's why your except block executes.
You really shouldn't be using try/except for situations where you can check the state using control flow logic.
Instead, in this case, check for if len(sys.argv) > 1.
Another reason never to use specifically a blank except: You will catch even system exceptions like SystemExit or KeyboardInterrupt, making it potentially impossible to terminate your program short of a messy kill.
I know you've already accepted an answer, but I think the root of the problem is that your try block contains code in which you do not necessarily wish to catch exceptions; rather, you merely wish these statements to be executed after the code in which you wish to catch exceptions if no exception occurs.
To address this, your try block should contain only filename=str(sys.argv[1]) and the rest of the code now in your try block should be moved to an else block, which will be executed only if no exception occurs. In other words:
try:
filename=str(sys.argv[1])
except:
print "ERROR"
sys.exit()
else:
if filename=="-mycommand":
print "SPECIFIC_TEXT"
sys.exit()
else:
return filename
Or in this case, since you exit the script entirely in the case of an exception, you don't actually need the else:
try:
filename=str(sys.argv[1])
except:
print "ERROR"
sys.exit()
if filename=="-mycommand":
print "SPECIFIC_TEXT"
sys.exit()
else:
return filename
The fact that you're catching every exception with your bare except is bad style and changing that would also avoid the problem, but to me, it's secondary. You do not wish to catch exceptions in your if/else code, so it should not be in the try block to begin with. IMHO, most admonitions against bare except would be moot if this guideline were followed more closely.