2011-02-02 12 views
6

El python documentation on array indica claramente que la matriz se ajusta a la interfaz del búfer. Incluso sugiere no utilizar el método buffer_info(). Pero cuando trato de obtener un Py_Buffer del código C/C++ con PyObject_GetBuffer() o uso la memoria de Python, obtengo un error.¿Por qué no es posible obtener un Py_buffer de un objeto de matriz?

Por ejemplo, en python (yo uso la versión 2.7):

>>> a = array.array('c') 
>>> memoryview(a) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: cannot make memory view because object does not have the buffer interface 

De hecho, cuando busco código base del pitón, solamente bytearrayobject (bytearray), memoryobject (memoryview), y stringobject (str) tienen el indicador Py_TPFLAGS_HAVE_NEWBUFFER requerido establecido en ellos. Según entiendo, la documentación es incorrecta; array no es compatible con la interfaz del búfer.

Podría usar bytearray, que es compatible con la interfaz del búfer, el problema es que necesito el práctico método fromfile() de la matriz para leer en un búfer que pueda usar en mi código C/C++.

¿Hay alguna alternativa que me permita leer un archivo en un búfer y usar este búfer desde el código C, y no involucrar copias de memoria? (Quiero tratar grandes archivos binarios y copiar es una opción menos deseable).

Respuesta

3

memoryview funciona solo en objetos que admiten la interfaz de búfer Python 3. array.array en Python 3 lo hace, pero no en Python 2.7. Es posible que desee presentar un informe de error para eso. Simplemente use bytearray (o str si está usando solo lectura). Ambos admiten memoryview bien.

+0

De acuerdo, como dije en mi pregunta. Pero ... bytearray no tiene el práctico método de archivo. Supongo que puedo usar un objeto de cadena para representar mis datos binarios, pero saber que un buffer (como bytearray) puede llenarse desde el archivo expande mis opciones. También está el caso de esquina unicode de una cadena que se eliminaría si pudiera usar otro tipo de buffer. – David

+2

El informe de error está aquí: http://bugs.python.org/issue17145 – mpb

2

Python 2.6+ tiene dos interfaces de búfer diferentes, al igual que tiene dos tipos de clases diferentes: la versión clásica y la versión de Python 3.

Desde el Python/C API Reference Manual:

Dos ejemplos de objetos que soportan la interfaz de memoria intermedia son cadenas y matrices. El objeto de cadena expone los contenidos de los caracteres en la forma orientada a bytes de la interfaz de buffer. Una matriz solo puede exponer sus contenidos a través de la interfaz de búfer antigua. Esta limitación no se aplica a Python 3, donde los objetos de vista de memoria también se pueden construir a partir de matrices.

En Python 2.7 código, se puede trabajar con las memorias intermedias de estilo antiguo con la función buffer, y tampones de nuevo estilo utilizando memoryview. Python 3 solo es compatible con este último.

Existe una distinción similar en Python 2 C API; PyObject_GetBuffer es para la nueva interfaz de búfer, PyBuffer_FromObject/PyBuffer_FromReadWriteObject es para la interfaz de búfer anterior (y debería funcionar para matrices). Vea el enlace de arriba para más información.

Cuestiones relacionadas