Python cython 中 dealloc 中的对象

Python objects in dealloc in cython

在文档中写道,"Any C data that you explicitly allocated (e.g. via malloc) in your __cinit__() method should be freed in your __dealloc__() method."

这不是我的情况。我有以下扩展 class:

cdef class SomeClass:
    cdef dict data
    cdef void * u_data

    def __init__(self, data_len):
        self.data = {'columns': []}
        if data_len > 0:
            self.data.update({'data': deque(maxlen=data_len)})
        else:
            self.data.update({'data': []})
        self.u_data = <void *>self.data

    @property
    def data(self):
        return self.data

    @data.setter
    def data(self, new_val: dict):
        self.data = new_val

一些 c 函数可以访问此 class 并将一些数据附加到 SomeClass().data 字典。当我想删除SomeClass()的实例时,__dealloc__中应该写什么?

可能是这样的:

def __dealloc__(self):
    self.data = None
    free(self.u_data)

或者根本不需要释放任何东西?

不,你不需要也不应该。来自 the documentation

You need to be careful what you do in a __dealloc__() method. By the time your __dealloc__() method is called, the object may already have been partially destroyed and may not be in a valid state as far as Python is concerned, so you should avoid invoking any Python operations which might touch the object. In particular, don’t call any other methods of the object or do anything which might cause the object to be resurrected. It’s best if you stick to just deallocating C data.

You don’t need to worry about deallocating Python attributes of your object, because that will be done for you by Cython after your __dealloc__() method returns.


您可以通过检查 C 代码来确认这一点(您需要查看完整代码,而不仅仅是带注释的 HTML)。有一个自动生成的函数 __pyx_tp_dealloc_9someclass_SomeClass(名称可能略有不同,具体取决于您对模块的称呼)执行一系列操作,包括:

__pyx_pw_9someclass_9SomeClass_3__dealloc__(o);
/* some other code */
Py_CLEAR(p->data);

其中函数 __pyx_pw_9someclass_9SomeClass_3__dealloc__ 是您的用户定义 __dealloc__ 的(包装器)。 Py_CLEAR 将确保 data 被适当地引用计数然后设置为 NULL.

这有点难以理解,因为它都经过了好几层包装器,但您可以确认它确实按照文档中的说明进行操作。