2011-02-10 15 views
9

sto ottenendo il seguente messaggio di avviso quando si tenta di utilizzare un array ctypes come un array NumPy:PEP 3118 avvertimento quando si utilizza ctypes matrice come NumPy serie

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) 

Il codice sembra funzionare, però. È una cattiva idea ignorare questo avvertimento?

Sfondo: Sto chiamando una DLL C che produce dati in tempo reale. Ho bisogno di passare alla DLL una serie di buffer per contenere i dati. Mentre aspetto il prossimo buffer da riempire, mi piacerebbe elaborare il buffer più recente con numpy e salvare il risultato. Sto generando i buffer con il codice come sopra, e le cose sembrano funzionare, ma non voglio spazzare un problema importante sotto il tappeto.

+1

È interessante notare che questo non sembra accadere con python2.6, solo python2.7 ... –

risposta

10

È un bug in Python. ctypes produce attualmente validi PEP 3118 codici tipo, quali NumPy comunicazioni: http://bugs.python.org/issue10746 http://bugs.python.org/issue10744

Quando tale incongruenza è presente, Numpy salta la utilizzando l'interfaccia tampone PEP 3118, e ricade al vecchio (obsoleto) interfaccia buffer. Questo dovrebbe funzionare correttamente.

È possibile disattivare l'avviso utilizzando il modulo warnings di Python. Tuttavia, l'avviso potrebbe avere un impatto sulle prestazioni.

Si può anche provare a risolvere il problema avvolgendo l'oggetto ctypes in buffer().

+0

Eccellente, grazie. Sono contento di sapere che si tratta di un bug noto e che non sto facendo qualcosa di stupido. – Andrew

+0

Qualcuno può commentare qualsiasi cambiamento nelle prestazioni avvolgendo gli oggetti ctypes con ['buffer()'] (http://docs.python.org/2/library/functions.html#buffer)? Questo metodo funziona in modo affidabile? In cosa differisce dal creare una nuova matrice numpy dall'array ctype EG: 'np.array (my_ctype_array [:]). Reshape ([back, to, original])' altri ringraziano maneggiando la forma? Ho pensato che 'ctypeslib.as_array()' fosse la pratica consigliata, ma il messaggio di avviso è davvero fastidioso e spegnerà gli utenti non tecnologici. Grazie. –

+1

Il wrapping degli oggetti ctypes con ['buffer()'] (http://docs.python.org/2/library/functions.html#buffer) ha fatto ** non ** il lavoro per me EG: 'new = numpy. ctypeslib.as_array (buffer (vecchio)) 'restituisce *** TypeError: buffer() richiede almeno 1 argomento (0 dato) ***. Qualcuno può aggiungere più chiarezza all'opzione wrap 'buffer()'? Grazie! –

3

C'è un modo più conveniente di fare questo, che evita l'avviso del tutto:

Invece di creare i dati come array ctypes prima e poi convertirlo in un array NumPy, basta crearlo come un array NumPy subito, quindi utilizzare numpy.ctypeslib.ndpointer come identificatore di tipo nel prototipo di ctypes. Per fare un esempio, diciamo che avete una funzione C chiamato f che prende un char* e size_t come argomenti:

void f(char* buf, size_t len); 

tuo ctypes prototipo sarebbe

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 

e si può chiamare questa funzione come

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

Molto bello! Non ho mai usato argtypes, ci proverò. – Andrew

Problemi correlati