[New-bugs-announce] [issue43533] Exception and contextmanager in __getattr__ causes reference cycle

Ran Chen report at bugs.python.org
Wed Mar 17 20:49:33 EDT 2021


New submission from Ran Chen <crccw at 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 <report at bugs.python.org>
<https://bugs.python.org/issue43533>
_______________________________________


More information about the New-bugs-announce mailing list