I have specified specific exception in different except block, but when I raise exchangelib.errors.ErrorFolderNotFound it goes to wrong except block (i.e it goes to TransportError except block.
I have this code :
import exchangelib
try:
#some code
raise exchangelib.errors.ErrorFolderNotFound
except exchangelib.errors.TransportError:
print("transport error caught")
except exchangelib.errors.ErrorFolderNotFound:
print("folder not found caught")
except Exception as e:
print("exception caught")
but when I move the ErrorFolderNotFound except block above the TransportError block it goes to the right block (i.e ErrorFolderNotFound except block)
import exchangelib
try:
#some code
raise exchangelib.errors.ErrorFolderNotFound
except exchangelib.errors.ErrorFolderNotFound:
print("folder not found caught")
except exchangelib.errors.TransportError:
print("transport error caught")
except Exception as e:
print("exception caught")
Why is this behavior occurring ,as I am giving specific exception in the except block ?.
Also if any other exception occurs which belong to the same family of exchangelib, it goes to except block which already has some specific exchangelib error defined in the except block, it should go to `except block of Exception
Here in below code , when error is raised ,it goes to TransportError except block, but logically it should go to Exception except block
import exchangelib
try:
#some code
raise exchangelib.errors.ErrorFolderNotFound
except exchangelib.errors.TransportError:
print("transport error caught")
except Exception as e:
print("exception caught")
Without knowing the hierarchy of the Exceptions in exchangelib.errors, I can only guess that ErrorFolderNotFound inherits from TransportError. I.e.,
class MyBaseError(BaseException):
pass
class TransportError(MyBaseError):
pass
class ErrorFolderNotFound(TransportError):
pass
try:
#some code
raise ErrorFolderNotFound
except TransportError:
print("transport error caught")
except ErrorFolderNotFound:
print("folder not found caught")
except Exception as e:
print("exception caught")
which will print out transport error caught
If we change the hierarchy so that ErrorFolderNotFound does not inherit from TransportError. I.e.,
class MyBaseError(BaseException):
pass
class TransportError(MyBaseError):
pass
class ErrorFolderNotFound(MyBaseError):
pass
try:
#some code
raise ErrorFolderNotFound
except TransportError:
print("transport error caught")
except ErrorFolderNotFound:
print("folder not found caught")
except Exception as e:
print("exception caught")
then we'll get folder not found caught
Related
I have the following code:
import time
try:
time.sleep(3)
raise Exception('error')
except Exception or KeyboardInterrupt:
print(">>> Error or keyboard interrupt")
I want to catch either error or key board interrupt. But currently, it catches only Exception, keyboard interrupt is not handled.
If I remove Exception and leave only Keyboard interrupt, it catches only keyboard interrupt.
If I remove KeyboardInterrupt and leave only Exception, it catches only Exception.
Is there a way to catch both ?
If you want to handle the two cases differently the best way of doing this is to have multiple except blocks:
import time
try:
time.sleep(3)
raise Exception('error')
except KeyboardInterrupt:
print("Keyboard interrupt")
except Exception as e:
print("Exception encountered:", e)
Mind the order!
According to https://docs.python.org/3/tutorial/errors.html#handling-exceptions
you can use
except (RuntimeError, TypeError, NameError):
import time
try:
time.sleep(3)
raise Exception('error')
except (Exception, KeyboardInterrupt):
print(">>> Error or keyboard interrupt")
Let's say I have a code that looks like this:
try:
raise ValueError()
except ValueError as err:
print("ValueError block")
raise
except Exception as err:
print("Exception block")
This prints:
ValueError block
and raises an exception. I want it to just print:
ValueError block
Exception block
Can I achieve that by somehow calling the Exception block from the ValueError block?
You have to obey the rules of exception handling. In this case, you can use a nested try block:
try:
try:
raise ValueError()
except ValueError as err:
print("ValueError block")
raise
except Exception as err:
print("Exception block")
Since ValueError is a subclass of Exception, you could write one except block and check with isinstance:
try:
raise ValueError()
except Exception as err:
if isinstance(err, ValueError):
print("ValueError block")
print("Exception block")
I have a script that catches all exceptions, which works great unless I want to abort the script manually (with control + c). In this case the abort command appears to be caught by the exception instead of quitting.
Is there a way to exclude this type of error from the exception? For example something as follows:
try:
do_thing()
except UserAbort:
break
except Exception as e:
print(e)
continue
You could just force to exit the program whenever the exception happens:
import sys
# ...
try:
do_thing()
except UserAbort:
break
except KeyboardInterrupt:
sys.exit()
pass
except Exception as e:
print(e)
continue
try:
raise KeyError()
except KeyError:
print "Caught KeyError"
raise Exception()
except Exception:
print "Caught Exception"
As expected, raising Exception() on the 5th line isn't caught in the final except Exception clause. In order the catch the exception inside of the except KeyError block, I have to add another try...except like this and duplicate the final except Exception logic:
try:
raise KeyError()
except KeyError:
print "Caught KeyError"
try:
raise Exception()
except Exception:
print "Caught Exception"
except Exception:
print "Caught Exception"
In Python, is it possible to pass the flow of execution to the final except Exception block like I am trying to do? If not, are there strategies for reducing the duplication of logic?
You could add another level of try nesting:
try:
try:
raise KeyError()
except KeyError:
print "Caught KeyError"
raise Exception()
except Exception:
print "Caught Exception"
Try:
#some statement
Try:
#some statement
Except:
#statement1
Raise exception()
#statement2
Except: #some statement
Can I pass the control like the above code in python., will the inner except pass the control to the outer except and will the #statement2 be executed?
This code will answer your question:
#!/usr/bin/env python
import sys
try:
try:
raise Exception("first exception")
except Exception as e:
print e.message
raise Exception("second exception")
print "second statement" # never printed - 'dead code'
except Exception as e:
print e.message
Both except blocks are executed but the statement after raising the second exception is not.
Generally you should know that once an exception is raised, nothing executes until it is caught by an except block that is relevant to this exception or any superclass of it.