python - Python 列表中的额外元素

标签 python cython

我正在尝试使用 Cython 将 Python 列表转换为 Cython 数组,反之亦然。 Python 列表包含 0 - 255 范围内的数字,因此我将数组类型指定为 unsigned char 数组。这是我进行转换的代码:

from libc.stdlib cimport malloc

cdef to_array(list pylist):
    cdef unsigned char *array 
    array = <unsigned char *>malloc(len(pylist) * sizeof(unsigned char))
    cdef long count = 0

    for item in pylist:
        array[count] = item
        count += 1
    return array

cdef to_list(array):
    pylist = [item for item in array]
    return pylist

def donothing(pylist):
    return to_list(to_array(pylist))

问题在于Cython数组中会产生一些垃圾数据,转换为Python列表时,垃圾数据会带走。例如,donothing 应该完全不做任何事情,并将 python 列表返回给我,保持不变。这个函数只是为了测试转换,但是当我运行它时,我得到类似的东西:

In[56]:  donothing([2,3,4,5])
Out[56]: [2, 3, 4, 5, 128, 28, 184, 6, 161, 148, 185, 69, 106, 101]

这些数据在代码中来自哪里,如何清理这些垃圾才不会浪费内存?

附言从 Python 列表中获取数字并将它们注入(inject) unsigned char 数组可能有更好的版本。如果是这样,请指导我完全采用更好的方法。

最佳答案

您的to_array 有一个未类型化的返回值。此外,您将结果分配给一个未类型化的值。因此,Cython 被迫将 char * 转换为 Python 类型。

Cython 转换为 bytes,因为 char 大约是 bytes。不幸的是,如果没有明确给出的长度,Cython 会假定 char * 是空终止的。这是导致问题的原因:

convert_lists.donothing([1, 2, 3, 0, 4, 5, 6])
#>>> [1, 2, 3]

当没有零时,Cython 将一直读取直到找到一个,越过实际分配的内存。

您实际上不能为任意 Cython 类型执行 for x in my_pointer_arrrayfor 循环实际上对错误转换的 bytes 进行操作。

您可以通过键入将保存 char 数组的 all 值来解决此问题,显式传递长度并在范围内循环(循环时也会更快)变量是类型化的),或者通过使用某种包装器。有关使用什么包装器数组的想法,this question and answer pair has you covered .


另请注意,在使用手动分配时,您应该非常小心错误。 malloc 的数据不会被垃圾收集,因此如果您在代码路径之外出错,您将泄漏内存。您应该检查如何处理每个特定案例。

关于python - Python 列表中的额外元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24102447/

相关文章:

python - 读取输入文件时更新 C 数组

python - 如何为 MacOSX 后端设置 matplotlib 窗口大小?

python - 根据条件从 pandas 系列中删除重复项

python - 如何使用 cython 编译扩展?

python - Cython 中的并行性不起作用

multithreading - Cython:使 prange 并行化线程安全

python - NumPy:如何左连接有重复的数组

python - 按键名合并字典值

python - 为什么 Python 3.3 中的打印速度如此之慢,我该如何解决?

python - 查找句子中单词序列的连续重复