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