New submission from Ran Chen <cr...@moonux.org>:
If __getattr__ raises exception within a contextlib.context_manager, it creates a reference cycle and prevents the frame from being garbage collected. This only happens if the exception is raised inside a context manager inside __getattr__. It doesn't happen if there's no context manager. Repro: ``` import contextlib import gc @contextlib.contextmanager def ct(): yield class A(object): def __getattr__(self, name): with ct(): raise AttributeError() def f(): a = A() hasattr(a, 'notexist') gc.set_debug(gc.DEBUG_LEAK) f() gc.collect() ``` It also doesn't happen if we catch the exception outside of the context manager and re-raise it: ``` def __getattr__(self, name): try: with ct(): raise AttributeError() except: raise ``` ---------- components: Library (Lib) messages: 388977 nosy: crccw priority: normal severity: normal status: open title: Exception and contextmanager in __getattr__ causes reference cycle type: behavior versions: Python 3.6 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue43533> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com