[Cython] Hooking tp_clear()

Stefan Behnel stefan_ml at behnel.de
Fri Sep 7 12:31:05 EDT 2018


Jeroen Demeyer schrieb am 07.09.2018 um 10:14:
> On 2018-09-07 06:35, Stefan Behnel wrote:
>> Maybe you actually want "tp_finalize"?
>>
>> https://www.python.org/dev/peps/pep-0442/
>>
>> Cython moves "__del__" methods there in Py3.4+.
> 
> First of all, are you sure? I tried to cythonize
> 
> cdef class X:
>     def __del__(self):
>         pass
> 
> but the generated C code has
> 
> static PyTypeObject __pyx_type_6cytest_X = {
>   /* ... */
>   #if PY_VERSION_HEX >= 0x030400a1
>   0, /*tp_finalize*/
>   #endif
> };

Interesting. I thought it did, but apparently, it doesn't. "__del__"
doesn't currently have any special meaning for extension types. Then let's
change that and give it the same meaning that PEP-442 gives it for Python
classes. Want to write a PR?


> In any case, I want something which works with Python 2.7 too. Could we
> somehow call __del__ from tp_clear() in Python 2.7?

That would be problematic, because tp_clear() is not guaranteed to be
called. Quite the contrary, it's only called if the object is so unlucky to
participate in a reference cycle that gets cleaned up. In that case, we
would have to call it twice (in tp_clear() and tp_dealloc()) in order to
make sure that it always gets called. In Py3.4+, it always gets called
separately before tp_clear() or tp_dealloc().

Can't you just wait a year or two … ? ;)

Or, since it's a new feature, we could just document that it gets called
twice in Py2 and that people should take care of writing their code
accordingly.

OTOH, the way PEP 442 guarantees that it only gets called once is by
setting a flag in the GC header. We could see if we can steal an unused
flag there to do the same thing in Py2.

Stefan


More information about the cython-devel mailing list