2011-02-10 22 views
9

Estoy recibiendo el mensaje de advertencia al intentar utilizar una matriz como una matriz ctypes numpy:PEP 3118 advertencia al utilizar ctypes matriz como matriz 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) 

El código parece estar funcionando, sin embargo. ¿Es una mala idea ignorar esta advertencia?

Antecedentes: Estoy llamando a una DLL de C que produce datos en tiempo real. Necesito pasar la DLL una serie de almacenamientos intermedios para contener los datos. Mientras espero a que se llene el siguiente buffer, me gustaría procesar el buffer más reciente con numpy y guardar el resultado. Estoy generando los buffers con el código anterior, y las cosas parecen estar funcionando, pero no quiero barrer un problema importante debajo de la alfombra.

+1

Curiosamente, esto no parece suceder con python2.6, solo python2.7 ... –

Respuesta

10

Es un error en Python. ctypes produce actualmente PEP 3118 códigos de tipo no válidos, que NumPy Advertencia: http://bugs.python.org/issue10746 http://bugs.python.org/issue10744

Cuando una inconsistencia tal está presente, Numpy omite la utilizando el interfaz de tampón PEP 3118, y cae de nuevo a la vieja (obsoleto) interfaz de buffer. Esto debería funcionar correctamente.

Puede silenciar la advertencia utilizando el módulo warnings de Python. Sin embargo, la advertencia puede tener un impacto en el rendimiento.

También puede intentar solucionar el problema envolviendo el objeto ctypes en buffer().

+0

Excelente, gracias. Me alegra saber que es un error conocido y no yo haciendo algo tonto. – Andrew

+0

¿Alguien puede comentar sobre cualquier cambio en el rendimiento envolviendo los objetos ctypes con ['buffer()'] (http://docs.python.org/2/library/functions.html#buffer)? ¿Funciona este método de manera confiable? ¿Cómo difiere de hacer una nueva matriz numpy de la matriz ctype? EG: 'np.array (my_ctype_array [:]). Reshape ([back, to, original])' ¿Otro agradecimiento por destruir la forma? Pensé que 'ctypeslib.as_array()' era la práctica recomendada, pero el mensaje de advertencia es realmente molesto y desactivará a los usuarios que no sean expertos en tecnología. Gracias. –

+1

Envolviendo los objetos ctypes con ['buffer()'] (http://docs.python.org/2/library/functions.html#buffer) ** no ** funcionó para mí EG: 'new = numpy. ctypeslib.as_array (buffer (old)) 'returns *** TypeError: buffer() toma al menos 1 argumento (0 dado) ***. ¿Alguien puede agregar más claridad a la opción de ajuste 'buffer()'? ¡Gracias! –

3

Hay una manera más conveniente de hacerlo, lo que evita el aviso completo:

En lugar de crear los datos como una matriz ctypes primero y luego convertirlo en una matriz NumPy, simplemente crearla como una matriz NumPy de inmediato, y luego use numpy.ctypeslib.ndpointer como especificador de tipo en su prototipo de ctypes. A modo de ejemplo, digamos que usted tiene una función C llamada f que toma un char* y una size_t como argumentos:

void f(char* buf, size_t len); 

Su ctypes prototipo habría

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 

y se puede llamar a esta función como

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

¡Muy bonito! No he usado argipos antes, voy a probar esto. – Andrew