Exception raised in both try and except . - python

def FancyDivide(list_of_numbers, index):
try:
try:
raise Exception("0")
finally:
denom = list_of_numbers[index]
for i in range(len(list_of_numbers)):
list_of_numbers[i] /= denom
except Exception, e:
print e
When function is called I got the following output.
FancyDivide([0, 2, 4], 0)
integer division or modulo by zero
In the try code an exception is raised. In finally also there is an exception .Why is it so that exception in the finally was caught not the exception in the try.

From the documentation -
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. When an exception has occurred in the try clause and has not been handled by an except clause (or it has occurred in a except or else clause), it is re-raised after the finally clause has been executed.
(Emphasis mine)
As given, the exception - Exception("0") would have only been raised again after completing the finally block. But because an exception occured in the finally block, it was raised instead of the Exception("0") .

Related

How to use nested try except properly in python3.7?

I have situation where I wanted to run some line of code and if those lines runs successfully then run another few lines. In both cases there are possibilities of errors/exceptions. So I wanted to know which would be the best way to use try catch between two I mentioned below
def function_name1():
try:
*Run first few lines*
try:
*Run second few lines*
except Exception as ex2:
raise Exception("second Exception - wdjk")
except Exception as ex1:
raise Exception("first Exception - wejk")
def function_name2():
try:
*Run first few lines*
except Exception as ex1:
raise Exception("first Exception - wejk")
try:
*Run second few lines*
except Exception as ex2:
raise Exception("second Exception - wdjk")
In function_name1, I faced one issue that even if I get excption in second line i.e raise Exception("second Exception - wdjk"), code is returning or raising exception from raise Exception("first Exception - wejk").
So what would be the best way to handle this case?
The cleanest solution would be to run the second try/except in the else suite of the first:
try:
# first stuff
except SomeException:
# error handling
else: # no error occurred
try:
# second stuff
except OtherException:
# more error handling
If the code blocks are independent from one another, I don't see why you would nest them. The second option would be better. You can learn more about exceptions in this post by Real Python: https://realpython.com/python-exceptions/ There they talk about how try-except works.

python: Exception flow: Continue to down catch block after catching?

I am curious if there is a way in python to continue on within try/catch block, after you catch an exception, look at its properties, and if not relevant, then continue down the stack.
try:
# Code
except AppleError as apple_ex:
# look at 'apple_ex.error_code' error body, and if not relevant,
# continue on to next down the catch block...
# In other words, proceed to except BananaError and so on down.
except BananaError as banana_ex:
# ...
except Exception as ex:
# ...
That is not how exceptions are handled in Python. When you raise an exception in a try block, if you handle catching it in the except, it will fall inside that block, but will not continue to the next except at that same level. Observe this functional example:
try:
raise AttributeError()
except AttributeError:
raise TypeError()
except TypeError:
print("it got caught") # will not catch the TypeError raised above
So, in your try, we raise an AttributeError, we catch it, and then raise a TypeError inside catching the AttributeError.
The except TypeError will not catch that TypeError.
Based on how you are explaining your problem, you need to rethink how you are handling your exceptions and see if you can determine the handling of errors somewhere else, and raise the error there.
For example:
def some_func():
try:
thing()
except SomeException:
# analyze the exception here and raise the error you *should* raise
if apple_error_thing:
raise AppleError
elif banana_error_thing:
raise BananaError
else:
raise UnknownException
def your_func():
try:
some_func()
except AppleError as e:
print('Apple')
except BananaError as e:
print('Banana')
except UnknownException as e:
print('Unknown')
An AppleError is still an AppleError and not a BananaError, even if error_code is not relevant, so it makes no sense to fall through to BananaError.
You could instead define specific errors for your different error codes:
GRANNY_SMITH_ERROR = 1
MACINTOSH_ERROR = 2
class AppleError(Exception):
def __init__(self, error_code, *args):
super(AppleError, self).__init__(*args)
self.error_code = error_code
class GrannySmithError(AppleError):
def __init__(self, *args):
super(GrannySmithError, self).__init__(GRANNY_SMITH_ERROR, *args)
class MacintoshError(AppleError):
def __init__(self, *args):
super(MacintoshError, self).__init__(MACINTOSH_ERROR, *args)
Then you can try to match the specific error:
try: raise MacintoshError()
except MacintoshError as exc: print("mac")
except GrannySmithError as exc: print("granny smith")
If you do not care to distinguish between different types of apple errors, you can still trap all apple errors:
try: raise MacintoshError()
except AppleError as exc: print("generic apple")
You can combine these, for example, only doing special processing for GrannySmith, not for Macintosh:
try: raise MacintoshError()
except GrannySmithError as exc: print("granny smith")
except AppleError as exc: print("generic apple")
The important thing is to list the errors from most specific to least specific. If you test for AppleError before GrannySmithError, then it will never enter the GrannySmith block.
No, that isn't possible. After the exception is handled by the inner except it doesn't have the ability to get handled by the outer except:
From the docs on the try statement:
When the end of this block is reached, execution continues normally after the entire try statement. (This means that if two nested handlers exist for the same exception, and the exception occurs in the try clause of the inner handler, the outer handler will not handle the exception.)
In short your only solution might be to have another handler at an outer level and re-raise the exception in the inner handler, that is:
try:
try:
raise ZeroDivisionError
except ZeroDivisionError as e:
print("caught")
raise ZeroDivisionError
except ZeroDivisionError as f:
print("caught")
Now the nested except raises an exception which is consequently caught by a similar handler.

How to handle exception chaining raised from the except block

In my example I have a custom exception class MyCustomException and in main I divide an integer a by zero which raises a ZeroDivisionError exception. With the except block I catch ZeroDivisionError and then raise MyCustomException from err; this creates a chained exception, my own, plus the one in err.
Now how can I catch chained exceptions or how do chained exceptions work? Python doen't let me to catch MyCustomException in my code with except block.
class MyCustomException(Exception):
pass
a=10
b=0
reuslt=None
try:
result=a/b
except ZeroDivisionError as err:
print("ZeroDivisionError -- ",err)
raise MyCustomException from err
except MyCustomException as e:
print("MyException",e) # unable to catch MyCustomException
The output I get when I execute it:
ZeroDivisionError -- division by zero
Traceback (most recent call last):
File "python", line 13, in <module>
MyCustomException
Using raise in the except clause won't search for exception handlers in the same try block (it did not occur in that try block).
It will search for handlers one level up , that is, an outer try block. If that isn't found it'll interrupt execution as it normally does (resulting in the exception being displayed).
In short, you need an enclosing try in the outer level with the appropriate except MyCustomException in order to catch your custom exception:
try:
try:
result=a/b
except ZeroDivisionError as err:
print("ZeroDivisionError -- ",err)
raise MyCustomException from err
except MyCustomException as e:
print("Caught MyException", e)
Which, when executed, now prints out:
ZeroDivisionError -- division by zero
Caught MyException

Boolean 'not' in Python exception catching

I try to construct a except clause that catches everything except [sic] a particular type of exception:
try:
try:
asdjaslk
except not NameError as ne: #I want this block to catch everything except NameError
print("!NameError- {0}: {1}".format(ne.__class__, ne))
except Exception as e: #NameError is the only one that should get here
print("Exception- {0}: {1}".format(e.__class__, e))
The language accepts the not in the except clause, but does nothing with it:
>>> Exception- <type 'exceptions.NameError'>: name 'asdjaslk' is not defined
Is it possible to do this or should I reraise them?
You'll have to re-raise. An except statement can only whitelist, not blacklist.
try:
asdjaslk
except Exception as ne:
if isinstance(ne, NameError):
raise
The not NameError expression returns False, so you are essentially trying to catch:
except False:
but no exception will ever match a boolean instance.
The syntax allows for any valid Python expression, and the thrown exception is matched against the outcome of that expression. except SomeException if debug else SomeOtherException: is perfectly valid, for example.
You can can try this:
try:
# your code raising exceptions
except NameError:
# catch the exception you don't want to catch
# but immediately raise it again:
print("re-raising NameError- {0}: {1}".format(ne.__class__, ne))
raise
except Exception as e:
# handle all other exceptions here
print("catching Exception- {0}: {1}".format(e.__class__, e))
pass

Handling all but one exception

How to handle all but one exception?
try:
something
except <any Exception except for a NoChildException>:
# handling
Something like this, except without destroying the original traceback:
try:
something
except NoChildException:
raise NoChildException
except Exception:
# handling
The answer is to simply do a bare raise:
try:
...
except NoChildException:
# optionally, do some stuff here and then ...
raise
except Exception:
# handling
This will re-raise the last thrown exception, with original stack trace intact (even if it's been handled!).
New to Python ... but is not this a viable answer?
I use it and apparently works.... and is linear.
try:
something
except NoChildException:
assert True
except Exception:
# handling
E.g., I use this to get rid of (in certain situation useless) return exception FileExistsError from os.mkdir.
That is my code is:
try:
os.mkdir(dbFileDir, mode=0o700)
except FileExistsError:
assert True
and I simply accept as an abort to execution the fact that the dir is not somehow accessible.
I'd offer this as an improvement on the accepted answer.
try:
dosomestuff()
except MySpecialException:
ttype, value, traceback = sys.exc_info()
raise ttype, value, traceback
except Exception as e:
mse = convert_to_myspecialexception_with_local_context(e, context)
raise mse
This approach improves on the accepted answer by maintaining the original stacktrace when MySpecialException is caught, so when your top-level exception handler logs the exception you'll get a traceback that points to where the original exception was thrown.
You can do type checking on exceptions! Simply write
try:
...
except Exception as e:
if type(e) == NoChildException:
raise
It still includes the original stack trace.
I found a context in which catching all errors but one is not a bad thing, namely unit testing.
If I have a method:
def my_method():
try:
something()
except IOError, e:
handle_it()
Then it could plausibly have a unit test that looks like:
def test_my_method():
try:
my_module.my_method()
except IOError, e:
print "shouldn't see this error message"
assert False
except Exception, e:
print "some other error message"
assert False
assert True
Because you have now detected that my_method just threw an unexpected exception.

Categories

Resources