¿Es esto un error? Demuestra lo que sucede cuando usa libtiff para extraer una imagen de un identificador de archivo tiff abierto. Funciona en python 2.xy no funciona en python 3.2.3
import os
# any file will work here, since it's not actually loading the tiff
# assuming it's big enough for the seek
filename = "/home/kostrom/git/wiredfool-pillow/Tests/images/multipage.tiff"
def test():
fp1 = open(filename, "rb")
buf1 = fp1.read(8)
fp1.seek(28)
fp1.read(2)
for x in range(16):
fp1.read(12)
fp1.read(4)
fd = os.dup(fp1.fileno())
os.lseek(fd, 28, os.SEEK_SET)
os.close(fd)
# this magically fixes it: fp1.tell()
fp1.seek(284)
expect_284 = fp1.tell()
print ("expected 284, actual %d" % expect_284)
test()
El resultado que siento que es un error es: esperado 284, real -504
Descomentar el fp1.tell () produce algunos ... efectos secundarios ... que estabilizan el controlador py3, y no sé por qué. También agradecería si alguien puede probar otras versiones de python3.
2 respuestas
os.dup
crea un descriptor de archivo duplicado que se refiere a la misma descripción de archivo abierto. Por lo tanto, os.lseek(fd, 28, SEEK_SET)
cambia la posición de búsqueda del archivo subyacente fp1
.
Los objetos de archivo de Python almacenan en caché la posición del archivo para evitar repetidas llamadas al sistema. El efecto secundario de esto es que cambiar la posición del archivo sin usar los métodos del objeto del archivo desincronizará la posición en caché y la posición real, lo que dará lugar a tonterías como las que ha observado.
Peor aún, debido a que Python almacena internamente los archivos, buscar fuera de los métodos de archivo podría causar que los datos devueltos sean incorrectos, lo que provocaría corrupción u otras cosas desagradables.
La documentación en bufferedio.c
notas que tell
se puede usar para reinicializar el valor almacenado en caché:
* The absolute position of the raw stream is cached, if possible, in the
`abs_pos` member. It must be updated every time an operation is done
on the raw stream. If not sure, it can be reinitialized by calling
_buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
also does it). To read it, use RAW_TELL().
No, esto no es un error. La io
biblioteca de Python 3, que le proporciona el objeto de archivo de una llamada open()
, le proporciona un objeto de archivo almacenado en la memoria intermedia . Para los archivos binarios, se le da una (subclase de) io.BufferedIOBase
.
El objeto de archivo Python 2 es mucho más primitivo, aunque puede usar io
biblioteca allí también.
Al buscar a nivel del sistema operativo, está pasando por alto el búfer y está eliminando el estado interno. En términos generales, como el médico le dijo al paciente quejándose de que pellizcarse la piel duele: no hagas eso .
Si tiene una necesidad apremiante de hacer esto de todos modos, al menos use el objeto de archivo sin procesar subyacente (una subclase de io.RawIOBase
clase) a través de atributo io.BufferedIO.raw
:
fp1 = open(filename, "rb").raw
Preguntas relacionadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.