Skip to content

Instantly share code, notes, and snippets.

@bstpierre
Created July 16, 2009 03:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save bstpierre/148135 to your computer and use it in GitHub Desktop.
Save bstpierre/148135 to your computer and use it in GitHub Desktop.
Python Exception Handling: Cleanup and Reraise
#!/usr/bin/python
#
# This code sample shows (what I hope to be) the right way to reraise an exception in the
# situation where you have to perform some cleanup before reraising.
#
cleaned_up = False
def raiser():
raise RuntimeError("this should be reported at line 10")
def cleanup_raises():
global cleaned_up
cleaned_up = True
raise RuntimeError("you should not see this!")
def reraiser1():
try:
raiser()
except RuntimeError, e:
try:
cleanup_raises()
except RuntimeError:
pass
# Wrong: stack trace reports this as the original scene of the
# crime. Location information should say line 10 but it doesn't
raise e
def reraiser2():
try:
raiser()
except RuntimeError, e:
try:
cleanup_raises()
except RuntimeError:
pass
# Wrong: stack trace reports cleanup_raises as the culprit. We
# want to know about raiser.
raise
def reraiser3():
try:
raiser()
except RuntimeError, e:
def cleanup():
try:
cleanup_raises()
except RuntimeError:
pass
cleanup()
# Right: Need to make sure that exceptions from cleanup_raises
# are handled in a separate scope. This reports the original
# exception location of raiser at line 10.
raise
def reraiser4():
try:
raiser()
except RuntimeError, e:
(_, _, traceback) = sys.exc_info()
try:
cleanup_raises()
except RuntimeError:
pass
# Right: Raise exception but provide original traceback
# info. (Note: must call sys.exc_info() before calling any
# other possible raiser.) This also reports raiser at line 10.
raise e, None, traceback
def reraiser5():
try:
raiser()
finally:
try:
cleanup_raises()
except RuntimeError:
pass
# Right: Don't even catch the original exception -- just clean
# up on the way out.
assert(cleaned_up)
import sys
variant = sys.argv[1]
if variant == '1':
reraiser1()
elif variant == '2':
reraiser2()
elif variant == '3':
reraiser3()
elif variant == '4':
reraiser4()
elif variant == '5':
reraiser5()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment