I found this strange behavior. Why is the error variable not garbage collected? If error is another object, this wouldn't happen.
import gc
import weakref
class MyException(Exception):
pass
def func():
try:
raise MyException()
except MyException as exc:
error = exc
return error
# Only for inspection
import dis
dis.dis(func)
# Only keep a weak reference to the exception
err = func()
ref = weakref.ref(err)
del err
# Check if anything refers to the exception
refs = gc.get_referrers(ref())
for ref_ in refs:
if ref_.__class__.__name__ == "frame":
print(ref_)The output with Python 3.12 is:Output: 7 0 RESUME 0
8 2 NOP
9 4 LOAD_GLOBAL 1 (NULL + MyException)
14 CALL 0
22 RAISE_VARARGS 1
>> 24 PUSH_EXC_INFO
10 26 LOAD_GLOBAL 0 (MyException)
36 CHECK_EXC_MATCH
38 POP_JUMP_IF_FALSE 13 (to 66)
40 STORE_FAST 0 (exc)
11 42 LOAD_FAST 0 (exc)
44 STORE_FAST 1 (error)
46 POP_EXCEPT
48 LOAD_CONST 0 (None)
50 STORE_FAST 0 (exc)
52 DELETE_FAST 0 (exc)
12 54 LOAD_FAST 1 (error)
56 RETURN_VALUE
>> 58 LOAD_CONST 0 (None)
60 STORE_FAST 0 (exc)
62 DELETE_FAST 0 (exc)
64 RERAISE 1
10 >> 66 RERAISE 0
>> 68 COPY 3
70 POP_EXCEPT
72 RERAISE 1
ExceptionTable:
4 to 22 -> 24 [0]
24 to 40 -> 68 [1] lasti
42 to 44 -> 58 [1] lasti
58 to 66 -> 68 [1] lasti
<frame at 0x7f37f9f4d3c0, file '/home/XXX/test.py', line 12, code func>
