New submission from Ran Chen <[email protected]>:
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 <[email protected]>
<https://bugs.python.org/issue43533>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com