I'm experimenting with asynchronous patterns in Python and was curious what happens if I define a __del__
method using async def
in Python 3.12.
For example:
class MyClass:
async def __del__(self):
print("Async __del__ called")
Is this valid Python syntax?
Will the coroutine be awaited automatically when the object is garbage collected? If not awaited, is there any warning or silent failure?
Has this behavior changed in recent versions (like 3.11 → 3.12)?
Is there any recommended way to run async cleanup logic upon object deletion?
No - it simply won't run.
Python is a language which have a set of rules for how its classes behave. So, there are the dunder methods that are called by the language itself in certain circumstances. And then, the behavior for an async function: more formally a "coroutine function": When first called, it will immediately return a "coroutine" - when that coroutine is awaited, and only then, the code inside the function is itself executed.
Therefore, it is possible to create an async __getitem__
for example - upon doing myclass[key]
in such a class, a coroutine, which is awaitable, is returned, so async_content = await myclass[key]
will work.
But for __del__
, its return value is ignored: nothing would await a returned coroutine. You'd at most get a warning as the program ends that it was not awaited.
I'd suggest you to look for the asynchronous context manager protocol instead, use your object in an async with :
block (it would be better than __del__
even for synchronous cases anyway) and put your asynchronous finalization code in the __aexit__
method instead.
(by the way, while it's nice to document this - for cases like this you could simply try to run your code and see the results: the learning experience is instant and much stronger than reading someone reasoning about it. )