0

I'm trying to figure out how to correctly handle the deletion of an object when there is an error in a piece of code.

It seem that when there is an Exception raised the object is maintainded alive, while I need the object to be deleted. How do I release the object ?

with the following exemple code:

class A():
    def __init__(self) -> None:
        print(f"A[{id(self)}] created")
    def __del__(self):
        print(f"A[{id(self)}] deletted !!")

def foo(obj):
    raise ValueError

when I run foo(A()) I obtain:

A[1813071794504] created
[... traceback ...]
ValueError:

but I have no deletion

when I run a = A(); del a I obtain what I was expecting:

A[1813073658952] created
A[1813073658952] deletted !!

precision: I am running that code with py3.7 in the interactive window of VSCode (if that change anything)

vuvu 700
  • 15
  • 4
  • 1
    `__del__` should not be used, as it is not very straightforward. See [Python's most DISLIKED \_\_dunder\_\_ (and what to use instead)](https://www.youtube.com/watch?v=IFjuQmlwXgU) by mCoding and [this question](https://stackoverflow.com/q/1481488). – InSync May 31 '23 at 14:24
  • How are you running the code? In a python shell or from the command line? – tdelaney May 31 '23 at 14:33
  • @InSync I use `__del__` in my exemple because with CPython it indicate when an object is collected, it is juste to have simple visual exemple – vuvu 700 May 31 '23 at 15:28

1 Answers1

0

This is because the exception keeps a traceback of the call stack frames and that can keep variables alive until the traceback itself is deleted. If you run from the python shell or other interactive tools, they likely keep the traceback alive for inspection until another exception occurs. Notice how calling foo(A()) again, causes the deletion as soon as the second exception happens.

>>> foo(A())
A[140015433609328] created
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
ValueError
>>> foo(A())
A[140015432558352] created
A[140015433609328] deletted !!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
ValueError
>>> 

If you add an exception handler and run from the command line you can see the deletion as the try/except clause ends.

class A():
    def __init__(self) -> None:
        print(f"A[{id(self)}] created")

    def __del__(self):
        print(f"A[{id(self)}] deletted !!")

def foo(obj):
    raise ValueError

try:
    foo(A())
except ValueError:
    print("handle exception")

print("exiting")

output

A[139771605026992] created
handle exception
A[139771605026992] deletted !!
exiting
tdelaney
  • 73,364
  • 6
  • 83
  • 116
  • Is there a way to clean the last traceback or is it only internal ? – vuvu 700 May 31 '23 at 15:27
  • It will depend on the tool, but usually using try/except is all you need. If you run a python program, an unhandled exception causes exit which deletes the object. Its unhandled exceptions in the python shell or other things like jupyter that can be a problem. – tdelaney May 31 '23 at 15:44