I have the following file:
from fabric.api import env, execute, run
env.hosts = ['1.2.3.4']
def taskA():
run('ls')
def main():
try:
execute(taskA)
except:
print "Exception Caught"
main()
I am able to see "Exception Caught" printed when I run this:
$ python test.py
[1.2.3.4] Executing task 'taskA'
[1.2.3.4] run: ls
Fatal error: Timed out trying to connect to 1.2.3.4 (tried 1 time)
Underlying exception:
timed out
Aborting.
Exception Caught
However, when I switch it to this:
def main():
try:
execute(taskA)
except Exception, e:
print "Exception Caught", e
main()
I don't see the exception being caught:
[1.2.3.4] run: ls
Fatal error: Timed out trying to connect to 1.2.3.4 (tried 1 time)
Underlying exception:
timed out
Aborting.
Is there a reason why I am able to catch the error in the code above and not below?
This exception does not derive from Exception
. It looks like a SystemExit
, which derives from BaseException
directly. except Exception
only catches instances of Exception
.
If you really want to catch absolutely all exceptions, you can do that with
except BaseException as e:
SystemExit
is thrown by sys.exit
and a few similar functions to cause an interpreter shutdown (or at least end the thread) while still running __exit__
methods and finally
blocks. It can also be thrown manually.
BaseException
exists so SystemExit
and a few similar exceptions aren't caught by except Exception
blocks that usually aren't intended to handle them. It's similar to Java's Throwable
. Personally, I wish plain except:
blocks didn't catch BaseException
; it defeats some of the purpose of having BaseException
in the first place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With