2011-02-10 79 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)