Message388977
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
``` |
|
Date |
User |
Action |
Args |
2021-03-18 00:49:33 | crccw | set | recipients:
+ crccw |
2021-03-18 00:49:33 | crccw | set | messageid: <1616028573.19.0.764954620341.issue43533@roundup.psfhosted.org> |
2021-03-18 00:49:33 | crccw | link | issue43533 messages |
2021-03-18 00:49:32 | crccw | create | |
|