Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6990831
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T19:24:34+00:00 2026-05-27T19:24:34+00:00

This is with Python 2.6.6 (default) on Debian Squeeze. Consider the following Python code.

  • 0

This is with Python 2.6.6 (default) on Debian Squeeze. Consider the following Python code.

import sys
try:
    raise Exception("error in main")
    pass
except:
    exc_info = sys.exc_info()
finally:
    try:
        print "cleanup - always run"
        raise Exception("error in cleanup")
    except:
        import traceback
        print >> sys.stderr, "Error in cleanup"
        traceback.print_exc()
    if 'exc_info' in locals():
        raise exc_info[0], exc_info[1], exc_info[2]

print "exited normally"

The error obtained is

Error in cleanup
Traceback (most recent call last):
  File "<stdin>", line 10, in <module>
Exception: error in cleanup
cleanup - always run
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
Exception: error in main

The idea is to cope with a situation where either some code or the cleanup of that code (which is always run) or both, gives an error. There is some discussion of this, for example, by Ian Bicking in Re-raising Exceptions. At the end of that post, (see Update:) he describes how to handle the similar case of code + rollback/revert (only run in case of error).

I fiddled with this and came up with the code above, which is a bit of a monstrosity. In particular, if there is only an error in
cleanup (commenting out raise Exception("error in main")), the code still exits normally, though it does print out a traceback. Currently, I’m giving the non-cleanup error priority, so it gets to stop the program.

Ideally I’d like either error to stop the program, but that doesn’t seem to easy to arrange. Python seems to only want to raise one error, losing the others if any, and by default it is usually the last one. Rearranging this gives rise to convolutions like above.

Also the use of locals() is a bit ugly. Can one do better?

EDIT: srgerg’s answer introduced me to the notion of the context managers and the with keyword. In addition to PEP 343, the other relevant bits of documentation I found are (in no particular order).
Context Manager Types, The with statement, and http://docs.python.org/reference/datamodel.html#context-managers. This certainly seems like a big improvement on previous approaches to this, i.e. spaghetti code involving trys, excepts, and finallys.

To summarize, there are two things that I want such a solution to give me.

  1. The ability for an exception in either the main code or in the
    cleanup to stop the program in its tracks. Context managers do this,
    because if the body of the with loop has an exception and the body of
    the exit does not, then that exception is propagated.
    If exit throws an exception and the body of the with loop does not,
    then that is propagated. if both throw an exception, then the exit
    exception is propagated and the one from the body of the while loop is
    suppressed. This is all documented i.e. from
    Context Manager Types,

    contextmanager.exit(exc_type, exc_val, exc_tb)

    Exit the runtime context and return a Boolean flag indicating if any exception that occurred should be suppressed. […]
    Returning a true value from this method will cause the with statement to suppress the exception and continue execution with the
    statement immediately following the with statement. Otherwise the exception continues propagating after this method has finished
    executing. Exceptions that occur during execution of this method will replace any exception that occurred in the body of the with
    statement. […] The exception passed in should never be reraised explicitly. instead, this method should return a false value to
    indicate that the method completed successfully and does not want to suppress the raised exception.

  2. If there are exceptions in both places, I want to see tracebacks
    from both, even if technically only one exception is thrown. This is
    true based on experimentation, because if both throw an exception,
    then the exit exception is propagated, but the traceback from the body
    of the while loop is still printed, as in
    srgerg’s answer.
    However, I can’t find this documented
    anywhere, which is unsatisfactory.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T19:24:35+00:00Added an answer on May 27, 2026 at 7:24 pm

    Ideally, you’d use the python with statement to handle the cleanup within the try ... except block, which would look something like this:

    class Something(object):
        def __enter__(self):
            print "Entering"
    
        def __exit__(self, t, v, tr):
            print "cleanup - always runs"
            raise Exception("Exception occurred during __exit__")
    
    try:
        with Something() as something:
            raise Exception("Exception occurred!")
    except Exception, e:
        print e
        import traceback
        traceback.print_exc(e)
    
    print "Exited normally!"
    

    When I run this, it prints:

    Entering
    cleanup - always runs
    Exception occurred during __exit__
    Traceback (most recent call last):
      File "s3.py", line 11, in <module>
        raise Exception("Exception occurred!")
      File "s3.py", line 7, in __exit__
        raise Exception("Exception occurred during __exit__")
    Exception: Exception occurred during __exit__
    Exited normally!
    

    Note, either exception will terminate the program, and can be dealt with in the except statement.

    Edit: According to the with statement documentation linked to above, the __exit__() method should only raise an exception if there is an error inside __exit__() – that is, it should not re-raise the exception passed into it.

    This is a problem if both the code in the with statement and the __exit__() method raise an exception. In that case, the exception that is caught in the except clause is the one raised in __exit__(). If you want the one raised in the with statement, you can do something like this:

    class Something(object):
        def __enter__(self):
            print "Entering"
    
        def __exit__(self, t, v, tr):
            print "cleanup - always runs"
            try:
                raise Exception("Exception occurred during __exit__")
            except Exception, e:
                if (t, v, tr) != (None, None, None):
                    # __exit__ called with an existing exception
                    return False
                else:
                    # __exit__ called with NO existing exception
                    raise
    
    try:
        with Something() as something:
            raise Exception("Exception occurred!")
            pass
    except Exception, e:
        print e
        traceback.print_exc(e)
        raise
    
    print "Exited normally!"
    

    This prints:

    Entering
    cleanup - always runs
    Exception occurred!
    Traceback (most recent call last):
      File "s2.py", line 22, in <module>
        raise Exception("Exception occurred!")
    Exception: Exception occurred!
    Traceback (most recent call last):
      File "s2.py", line 22, in <module>
       raise Exception("Exception occurred!")
    Exception: Exception occurred!
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Consider this python program: import sys lc = 0 for line in open(sys.argv[1]): lc
Consider this Python code for printing a list of comma separated values for element
/Users/smcho/Desktop/bracket/[10,20] directory has abc.txt, but when I run this Python code import glob import
Consider the following Python script, which uses SQLAlchemy and the Python multiprocessing module. This
I know python functions are virtual by default. Let's say I have this: class
Consider this Python program which uses PyGtk and Hippo Canvas to display a clickable
Consider this Python snippet: for a in range(10): if a == 7: pass if
I was given this Python code that would calculate an MD5 value for any
For an uncaught exception, Python by default prints a stack trace, the exception itself,
I often see python code that takes default arguments and has special behaviour when

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.