2011-02-10 47 views
9

我得到以下警告消息时,我尝试使用一个ctypes数组作为numpy的阵列3118警告:PEP使用ctypes的数组时作为numpy的阵列

Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on 
win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import ctypes, numpy 
>>> TenByteBuffer = ctypes.c_ubyte * 10 
>>> a = TenByteBuffer() 
>>> b = numpy.ctypeslib.as_array(a) 
C:\Python27\lib\site-packages\numpy\ctypeslib.py:402: RuntimeWarning: Item size 
computed from the PEP 3118 buffer format string does not match the actual item s 
ize. 
    return array(obj, copy=False) 
>>> b 
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=uint8) 

的代码似乎工作,但。忽略此警告是不是一个好主意?

背景: 我正在调用一个实时生成数据的C DLL。我需要通过DLL一系列缓冲区来保存数据。在等待下一个缓冲区填充时,我想用numpy处理最新的缓冲区并保存结果。我用上面的代码生成缓冲区,并且事情似乎正在工作,但我不想在地毯下扫除一个重要问题。

+1

有趣的是,这似乎并没有发生与python2.6,只有python2.7 ... – 2011-02-11 00:21:47

回答

10

这是Python中的一个错误。 ctypes的目前生产无效PEP 3118类型的代码,其中numpy的通知: http://bugs.python.org/issue10746 http://bugs.python.org/issue10744

当这种不一致的存在,numpy的跳过使用PEP 3118缓冲器接口,并回退到旧的(废弃的)缓冲器的接口。这应该正常工作。

您可以使用Python的warnings模块来消除警告。但是,警告可能会对性能产生影响。

您也可以尝试通过将ctypes对象包装在buffer()中来解决该问题。

+0

非常好,谢谢。很高兴知道这是一个已知的错误,而不是我在做一些愚蠢的事情。 – Andrew 2011-02-11 17:46:56

+0

任何人都可以通过用[`buffer()`](http://docs.python.org/2/library/functions.html#buffer)包装ctypes对象来评论性能的任何变化吗?这种方法可靠地工作吗?它与从ctype数组EG创建一个新的numpy数组有什么不同:`np.array(my_ctype_array [:])。reshape([back,to,original])`其他的感谢篡改形状?我认为`ctypeslib.as_array()`是推荐的做法,但警告信息真的很烦人,它会关闭非技术用户。谢谢。 – 2013-08-20 22:14:36

3

有这样做的更方便的方式,这就完全避免了警告:

而是首先创建的数据作为一个ctypes数组,然后将其转换为NumPy的阵列的,只是将其创建为NumPy的阵列马上,然后在您的ctypes原型中使用numpy.ctypeslib.ndpointer作为类型说明符。举个例子,假设你有一个名为f一个C函数,它接受一个char*size_t作为参数:

void f(char* buf, size_t len); 

你ctypes的原型是

from numpy.ctypeslib import ndpointer 
some_dll = ctypes.CDLL(...) 
some_dll.f.argtypes = [ndpointer(numpy.uint8, flags="C_CONTIGUOUS"), 
         ctypes.c_size_t] 
some_dll.f.restype = None 

,你可以调用这个函数作为

a = numpy.zeros(10, numpy.uint8) 
f(a, a.size)