[Python-Dev] Reference cycles in Exception.traceback (original) (raw)

Victor Stinner victor.stinner at gmail.com
Wed Mar 5 17:37:12 CET 2014


Hi,

Python 3 now stores the traceback object in Exception.traceback and exceptions can be chained through Exception.context. It's convinient but it introduced tricky reference cycles if the exception object is used out of the except block.

Refrences: Exception.traceback -> traceback -> frames -> local variables

Exception.traceback keeps strong references to local variables which will only be deleted after the exception is destroyed.

It becomes worse if the exception is stored in an object which is also a local variables somewhere in the traceback:

DebugObject -> Exception -> ... frame -> DebugObject

For a concrete example of object storing an exception, see Future.set_exception() of the ayncio module.

Python 3.4 introduced frame.clear(), but frame.clear() raises an RuntimeError if the frame is still running. And it doesn't break all reference cycles.

An obvious workaround is to store the traceback as text, but this operation is "expensive" especially if the traceback is only needed in rare cases.

I tried to write "views" of the traceback (and frames), but Exception.traceback rejects types other than traceback and traceback instances cannot be created. It's possible to store the traceback somewhere else and set Exception.traceback to None, but there is still the problem with chained exceptions.

Any idea for a generic fix to such problem?

Another workaround is to set Exception.traceback to None in release mode, and leaves it unchanged in debug mode. But it's not a good solution because bugs also occur in production, and most tricky bugs only occur in production :-)

For more info, see:

http://bugs.python.org/issue20032 http://code.google.com/p/tulip/issues/detail?id=42 http://code.google.com/p/tulip/issues/detail?id=155

Victor



More information about the Python-Dev mailing list