¿Por qué no es posible obtener un py_buffer de un objeto de matriz?
-
28-10-2019 - |
Pregunta
los Documentación de Python en la matriz afirma claramente que el formación se ajusta a la interfaz del búfer. Incluso sugiere no usar el método buffer_info (). Pero cuando trato de obtener un código Py_Buffer del código C/C ++ con pyobject_getbuffer () o uso MemoryView de Python, obtengo una falla.
Por ejemplo, en Python (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 la base de código de Python, solo bytearrayObject (bytearray), memoriaObject (MemoryView) y StringObject (str) tienen la bandera PY_TPFLAGS_HAVE_NEWBUFER requerida establecida en ellos. A mi opinión, la documentación es incorrecta; formación no admite la interfaz de búfer.
Podría usar ByteArray que admite la interfaz de búfer, el problema es que necesito el método práctico de la matriz fromFile () para leer en un búfer que puedo usar en mi código C/C ++.
¿Hay una alternativa que me permita leer un archivo en un búfer y usar este búfer del código C, y no involucrar copias de memoria? (Quiero tratar los grandes archivos binarios y la copia es una opción menos deseable).
Solución
memoryview
Funciona solo en objetos que admiten la interfaz Python 3 Buffer. array.array
En Python 3 sí, pero no lo hace en Python 2.7. Es posible que desee presentar un informe de error para eso. Simplemente use el uso bytearray
(o str
Si lo está usando de solo lectura). Ambos soporte memoryview
bien.
Otros consejos
Python 2.6+ tiene dos interfaces de búfer diferentes, al igual que tiene dos tipos de clase diferentes: la versión clásica y la versión Python 3.
Desde el Manual de referencia de Python/C API:
Dos ejemplos de objetos que admiten la interfaz de búfer son cadenas y matrices. El objeto de cadena expone el contenido del personaje en la forma orientada a bytes de la interfaz de búfer. Una matriz solo puede exponer su contenido a través de la interfaz de búfer de estilo antiguo. Esta limitación no se aplica a Python 3, donde los objetos de MemoryView también se pueden construir a partir de matrices.
En el código Python 2.7, puede trabajar con los buffers de estilo antiguo utilizando el buffer
función y buffers de nuevo estilo utilizando memoryview
. Python 3 solo apoya a este último.
Existe una distinción similar en la API de Python 2 C; PyObject_GetBuffer
es para la nueva interfaz de búfer, PyBuffer_FromObject
/PyBuffer_FromReadWriteObject
es para la antigua interfaz de búfer (y debería funcionar para matrices). Consulte el enlace anterior para obtener más información.