Catch all exceptions except user abort - python

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

Related

Python: catch Exception or keyboard interrupt

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

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

Python traceback.print_exc() returns 'None'

This function is supposed to catch exceptions in the main execution. If there is an exception it should print out the error with log.error(traceback.print_exc()) and clean up with exit_main().
def main():
try:
exec_app()
except KeyboardInterrupt:
log.error('Error: Backup aborted by user.')
exit_main()
except Exception:
log.error('Error: An Exception was thrown.')
log.error("-" * 60)
log.error(traceback.print_exc())
log.error("-" * 60)
exit_main()
Unfortunately log.error(traceback.print_exc()) does only return None if there is an exception. How can I make traceback print the full error report in this case?
PS: I use python 3.4.
From its __doc__:
Shorthand for 'print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback, limit, file)'
That is, it isn't supposed to return anything, its job is to print. If you want the traceback as a string to be logged, use traceback.format_exc() instead.
I usually use traceback.print_exc() just for debugging. In your case, to log your exception you can simply do the following:
try:
# Your code that might raise exceptions
except SomeSpecificException as e:
# Do something (log the exception, rollback, etc)
except Exception as e:
log.error(e) # or log(e.message) if you want to log only the message and not all the error stack

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