How to execute something if any exception happens - exception

A python newbie question: I need to do the following
try:
do-something()
except error1:
...
except error2:
...
except:
...
#Here I need to do something if any exception of the above exception was thrown.
I can set a flag and do this. But is there a cleaner way of doing this?

Actually I don't like flags and consider them as the last resort solution. In this case I'd consider something like this:
def f():
try:
do_something()
except E1:
handle_E1()
except E2:
handle_E2()
else:
return
do_stuff_to_be_done_in_case_any_exception_occurred()
Of course, this is only an option if you can return in the else: case.
Another option might be to rethrow the exception and recatch it for a more general handling of errors. This might even be the cleanest approach:
def f():
try: # general error handling
try: # specific error handling
do_something()
except E1:
handle_E1()
raise
except E2:
handle_E2()
raise
except (E1, E2):
do_stuff_to_be_done_in_case_any_exception_occurred()

I just tried a couple different idea's out and it looks like a flag is your best bet.
else suite is only called if there is no exception
finally will always be called

You can do this with a nested try. The except block of the outer try should catch all exceptions. Its body is another try that immediately re-raises the exception. The except blocks of the inner try actually handle the individual exceptions. You can use the finally block in the inner try to do what you want: run something after any exception, but only after an exception.
Here is a little interactive example (modeled on Applesoft BASIC for nostalgia purposes).
try:
input("]") # for Python 3: eval(input("]"))
except:
try:
#Here do something if any exception was thrown.
raise
except SyntaxError:
print "?SYNTAX",
except ValueError:
print "?ILLEGAL QUANTITY",
# additional handlers here
except:
print "?UNKNOWN",
finally:
print "ERROR"

This is the best way I can think of. Looks like a code smell though
try:
exception_flag = True
do-something()
exception_flag = False
except error1:
...
except error2:
...
except:
...
finally:
if exception_flag:
...
You wouldn't need the finally if you are not reraising exceptions in the handler

From the docs: http://docs.python.org/reference/compound_stmts.html#finally
If finally is present, it specifies a ‘cleanup’ handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception, it is re-raised at the end of the finally clause. If the finally clause raises another exception or executes a return or break statement, the saved exception is lost. The exception information is not available to the program during execution of the finally clause.

It's not clear if you need to handle differently error1, error2 etc. If not, then the following code will do the trick:
try:
do_something()
except (error1, error2, error3), exception_variable:
handle_any_of_these_exceptions()
if you do need to handle different errors differently as well as having the common code, then in the except block, you can have code of the following type:
if isinstance(exception_variable, error1):
do_things_specific_to_error1()

I think this is a more neat solution by using return in the try clause.
If everything works, we will return the value we got in bar(). If we get an exception, we will run the next code, in this case raising another exception.
Demonstrated with a randint.
import random
def foo():
try:
return bar()
except IndexError:
print('Error.')
raise KeyError('Error msg')
def bar():
res = random.randint(0, 2)
if res == 0:
raise IndexError
return res
res = foo()
print(res)

Related

Robot Framework Succeed on Exception

I am testing a software component and want that software to throw an Exception in certain situations.
I want to reproduce these situations by using the robot framework.
The testcase shall succeed if I catch a specific Exception (which I am expecting, because I am deliberately creating an error-state in my component under test)
The testcase shall fail if I do not receive the specific Exception (i.e. my component under test did not fail(throw an exception) in an error situation)
What I am looking for is something like this:
prepareErrorInTestEnvironment
try
executeComponentWhichThrowsException
except
pass
fail
Treatment of "expected exception" are a bit specific in Robot Framework as usually exception will fail the keyword and hence the test.
The keyword you are looking for is Run Keyword and Expect Error.
Your test would look like
*** Test Cases ***
my test
prepareErrorInTestEnvironment
Run Keyword and Expect Error TheExceptionYouExpect executeComponentWhichThrowsException
This will success if you get the proper exception, and fail otherwise
I believe try/else is what you want
prepareErrorInTestEnvironment
try:
executeComponentWhichThrowsException
except:
pass
else:
fail
Also you can return on except so fail will not execute:
prepareErrorInTestEnvironment
try:
executeComponentWhichThrowsException
except:
*dosomething*
return
fail

Proper way to express application-specific exceptions

I'm trying to find a good way to express exceptions in dynamic-typed languages (e.g. Python, although the same code can be used with e.g. enums in static-typed languages). In my application, the exception is not going to be displayed to the user. Which one would be best? (or you can propose better)
def parseData(data):
length = unpack('!L', data[0:4])
if 4 + len(data) != length:
Option 1:
raise Exception("Invalid length")
Option 2:
return -1
# Some code later...
parseResult = parseData(data)
if validationResult == -1:
# Do something with the error.
The point is that when user doesn't see the exception, is it worth the hassle of making custom exception types instead of coming the easy path and returning integer values? (this is often done in functions like .indexOf(...)).
I can only comment on Python, but I would only extremely rarely raise Exception, as it makes error handling much harder; except Exception would catch many legitimate errors I would much rather hear about.
Instead, I would raise something more meaningful from the built-in exceptions:
raise ValueError("Invalid length.")
Most of Python's built-in classes and functions would raise an exception rather than returning some flag value. The only exception I can immediately think of is str.find, which will return -1 if the sub-string can't be found (its partner str.index will raise ValueError; I find this preferable, as -1 is a valid index).
There may be the occasional case where a single function could raise one of a range of exceptions, depending on what exactly has happened, but this is unusual - if your response will depend on what went wrong, that logic should probably be inside the function. You can still stick to the built-ins, for example:
def divide(n, lst, index):
return n / lst[index]
could raise TypeError, IndexError or ZeroDivisionError, and I can deal with that accordingly:
try:
divide(1, {3: 4, 5: 6}, 2)
except TypeError:
...
except IndexError:
...
except ZeroDivisionError:
...
except Exception as e:
print("Didn't see that coming: {0}".format(repr(e)))
You can even inspect the message in the exception to differentiate, if necessary:
def test():
test()
try:
test()
except RuntimeError as e:
if "recursion" in e.args[0]
print("Ran out of stack.")
else:
print("That was unexpected: {0}".format(repr(e)))

raising exceptions without printing

Is there any way to raise manually created exceptions without printing or returning anything? Would pass be sufficient or is there another way?
try:
a = b
raise user_error:
except user_error:
pass
All exceptions are derived from Exceptions() so you may create your own exception class and then raise it where ever you want. If your exception isn't caught in a try-except block it will be printed. Here's how to create your own exception, raise it and catch it:
class MyException(Exception):
def __str__(self):
print("Hello!")
try:
raise MyException
except MyException:
print("Found my own exception! :)")

Python - pythoncom.com_error handling in Python 3.2.2

I am using Python 3.2.2, and building a Tkinter interface to do some Active Directory updating. I am having trouble trying to handle pythoncom.com_error exceptions.
I grabbed some code from here:
http://code.activestate.com/recipes/303345-create-an-account-in-ms-active-directory/
However, I use the following (straight from the above site) handle the exceptions raised:
except pythoncom.com_error,(hr,msg,exc,arg):
This code is consistent with many of the sites I have seen that handle these exceptions, however with Python 3.2.2, I get a syntax error if I include the comma after "pythoncom.com_error". If I remove the comma, the program starts, but then when the exception is raised, I get other exceptions because "hr", "msg" etc are not defined as global variables.
If I remove the comma and all of the bits in the brackets, then it all works well, except I can't see exactly what happens in the exception, which I want so I can pass through the actual error message from AD.
Does anyone know how to handle these pythoncom exceptions properly in Python 3.2.2?
Thanks in advance!
You simply need to use the modern except-as syntax, I think:
import pythoncom
import win32com
import win32com.client
location = 'fred'
try:
ad_obj=win32com.client.GetObject(location)
except pythoncom.com_error as error:
print (error)
print (vars(error))
print (error.args)
hr,msg,exc,arg = error.args
which produces
(-2147221020, 'Invalid syntax', None, None)
{'excepinfo': None, 'hresult': -2147221020, 'strerror': 'Invalid syntax', 'argerror': None}
(-2147221020, 'Invalid syntax', None, None)
for me [although I'm never sure whether the args order is really what it looks like, so I'd probably refer to the keys explicitly; someone else may know for sure.]
I use this structure (Python 3.5) --
try:
...
except Exception as e:
print ("error in level argument", e)
...
else:
...

How to catch Exception Message in Erlang?

This is the Exception message thrown by Gen_server when its not started.
(ankit#127.0.0.1)32> R11 = system_warning:self_test("SysWarn").
** exception exit: {noproc,
{gen_server,call,
[system_warning_sup,
{start_child,
{system_warning_SysWarn,
{system_warning,start_link,[{system_warning_SysWarn}]},
permanent,10,worker,
[system_warning]}},
infinity]}}
in function gen_server:call/3
in call from system_warning_sup:'-start_child/1-lc$^0/1-0-'/1
in call from system_warning:self_test/1
(ankit#127.0.0.1)33> R11.
* 1: variable 'R11' is unbound
Now, What I want to do is to catch this exception message & put into variable R11 (showed above as unbound). I want to do so because if gen_sever is not started then I want to start after getting this message. I also tried using handle_info but not able to trap the exception or may be not able to implement it correctly. Can any body please help me with this problem providing some code for example.
Both the answers from #W55tKQbuRu28Q4xv and #Zed are correct but a little terse. :-)
There are two ways to locally catch an error: catchand try. Both will also catch non-local returns generated by throw.
catch is the older and simpler of the two and has the syntax catch Expr. If an error occurs in the expression being evaluated then catch returns {'EXIT',ErrorValue}, otherwise it just returns the value of the expression. One problem with it is that there is no way to see how the error return value has been generated so it can easily be faked in the expression. In the same way you can't see if the return value comes from a throw. N.B. this is not a bug but a feature. Also it is a prefix operator with a low priority so you would normally use it like:
R11 = (catch system_warning:self_test (....))
to avoid confusion. This was a mistake, it should have been catch ... end.
throw is more complex and allows you much greater control over over what to catch and how to handle both the normal returns and error/non-local returns. See the manual for a full description. #Zed's example shows the simplest case which catches everything.
> try
> R11 = system_warning:self_test("SysWarn")
> catch
> Ex:Type -> {Ex,Type,erlang:get_stacktrace()}
> end.
Try to use 'catch':
R11 = catch system_warning:self_test (....)