Python: catch Exception or keyboard interrupt - python

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")

Related

Exit script from inside of try-catch block in Python 3

I'm trying to exit a script from inside a try: except: block except it just goes on to the exception case.
None of these...
try:
exit()
except:
pass()
try:
quit()
except:
pass
import sys
try:
sys.exit()
except:
pass
...exit my script, they just go on to the except case.
How would I exit my script from inside one of these blocks?
All of these examples raise the SystemExit exception and you are catching that exception, a blank except clause will catch all exceptions.
This is the reason why you should always specify the exception you intend to catch or at least use except Exception eg
try:
exit()
except Exception:
pass
try:
quit()
except Exception:
pass
import sys
try:
sys.exit()
except Exception:
pass
With that change in place, all of you examples will cause your Python app to exit

Catch all exceptions except user abort

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

Python Try/Except with multiple except blocks

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"

nested try except in python

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.

How to exit a loop on exception, but not re-raise every Exception type?

I have a loop that I want to terminate on KeyboardInterrupt:
while True:
try:
do_stuff()
except KeyboardInterrupt:
cleanup()
break
except Exception as e:
cleanup()
raise e
This works fine, but the dual cleanup() seems very unclean to me. I don't like duplicated code. I tried using a context manager instead, but that introduced a lot of unnecessary complexity and nearly doubled the file size.
Is there a cleaner way to express my intent?
The finally keyword is exactly what you are looking for. The doc on errors and exceptions explains its usage.
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not
If the cleanup is only supposed to occur when leaving the loop, I suggest swapping the loop and the try :
try:
while True:
do_stuff()
except KeyboardInterrupt:
pass
finally:
cleanup()
You can use BaseException to catch both
try:
do_stuff():
except BaseException as e:
cleanup()
if isinstance(e, KeyboardInterruption):
break
raise e
Also, you can use only raise instead of raise e
Sounds like you want the finally clause:
while True:
try:
do_stuff()
except KeyboardInterrupt:
break
finally:
cleanup()
cleanup() will always be called, whether or not the exception is raised or caught.

Categories