views:

116

answers:

2

I would like to write a function in Python (2.6) that can determine if it is being called from exception handling code somewhere up the stack.

This is for a specialized logging use. In python's logging module, the caller has to explicitly specify that exception information should be logged (either by calling logger.exception() or by using the exc_info keyword). I would like my logger to do this automatically, based on whether it is being called from within exception handling code.

I thought that checking sys.exc_info() might be the answer, but it also returns exception information from an already-handled exception. (From the docs: "This function returns a tuple of three values that give information about the exception that is currently being handled... If the current stack frame is not handling an exception, the information is taken from the calling stack frame, or its caller, and so on until a stack frame is found that is handling an exception. Here, 'handling an exception' is defined as 'executing or having executed an except clause.'")

Also, since I want this to be transparent to the caller, I do not want to have to use exc_clear() or anything else in the except clause.

What's the right way to do this?

+2  A: 

If you clear the exception using sys.exc_clear in your exception handlers, then sys.exc_info should work for you. For example: If you run the following script:

import sys

try:
    1 / 0
except:
    print sys.exc_info()
    sys.exc_clear()
print sys.exc_info()

You should see this output:

(, ZeroDivisionError('integer division or modulo by zero',), )
(None, None, None)

Update: I don't believe there is a simple ("transparent") way of answering the question "Is an exception handler running?" without going to some trouble, and in my opinion it's not worth taking the trouble just for logging. It is of course easy to answer the question "Has an exception been raised (in this thread)?", even on a per-stack-frame basis (see the documentation for frame objects).

Vinay Sajip
Thanks Vinay, but I'm looking for a way to do this that is transparent to the caller; that is, that doesn't require anything special in the except clause. I'll edit the question to be more specific.
A: 

Like everything in Python, an exception is an object. Therefore, you could keep a (weak!) reference to the last exception handled and then use sys.exc_info(). Note: in case of multithreading code, you may have issues with this approach. And there could be other corner cases as well.

However, explicit is better than implicit; are you really sure that handling exception logging in the same way as normal one is a good feature to add to your system?
In my humble opinion, not.

Roberto Liffredo