Diferencia entre `open` y `io.BytesIO` en flujos binarios
Para simplificar, vamos a considerar la escritura en lugar de la lectura por ahora.
Así que cuando usas open()
como por ejemplo:
with open("test.dat", "wb") as f: f.write(b"Hello World") f.write(b"Hello World") f.write(b"Hello World")
Después de ejecutar eso se creará un archivo llamado test.dat
que contiene 3x Hello World
. Los datos no se mantendrán en la memoria después de ser escritos en el archivo (a menos que sean guardados por un nombre).
Ahora bien, cuando consideras io.BytesIO()
en su lugar:
with io.BytesIO() as f: f.write(b"Hello World") f.write(b"Hello World") f.write(b"Hello World")
Que en lugar de escribir el contenido en un archivo, se escribe en un buffer en memoria. En otras palabras un trozo de RAM. Esencialmente escribir lo siguiente sería el equivalente:
buffer = b""buffer += b"Hello World"buffer += b"Hello World"buffer += b"Hello World"
En relación al ejemplo con la sentencia with, entonces al final también habría un del buffer
.
La diferencia clave aquí es la optimización y el rendimiento. io.BytesIO
es capaz de hacer algunas optimizaciones que lo hacen más rápido que simplemente concatenar todos los b"Hello World"
uno a uno.
Sólo para probarlo aquí hay un pequeño benchmark:
- Concat: 1,3529 segundos
- BytesIO: 0.0090 segundos
import ioimport timebegin = time.time()buffer = b""for i in range(0, 50000): buffer += b"Hello World"end = time.time()seconds = end - beginprint("Concat:", seconds)begin = time.time()buffer = io.BytesIO()for i in range(0, 50000): buffer.write(b"Hello World")end = time.time()seconds = end - beginprint("BytesIO:", seconds)
Además de la ganancia de rendimiento, usar BytesIO
en lugar de concatenar tiene la ventaja de que BytesIO
puede usarse en lugar de un objeto archivo. Así que digamos que usted tiene una función que espera un objeto de archivo para escribir. Entonces puedes darle ese buffer en memoria en lugar de un archivo.
La diferencia es que open("myfile.jpg", "rb")
simplemente carga y devuelve el contenido de myfile.jpg
; mientras que, BytesIO
de nuevo es sólo un buffer que contiene algunos datos.
Dado que BytesIO
es sólo un buffer – si quisieras escribir el contenido en un archivo más tarde – tendrías que hacer:
buffer = io.BytesIO()# ...with open("test.dat", "wb") as f: f.write(buffer.getvalue())
Además, no has mencionado una versión; estoy usando Python 3. Relacionado con los ejemplos: Estoy usando la sentencia with en lugar de llamar a f.close()