Differenza tra `open` e `io.BytesIO` nei flussi binari
Per semplicità, consideriamo la scrittura invece della lettura per ora.
Quindi quando si usa open()
come dire:
with open("test.dat", "wb") as f: f.write(b"Hello World") f.write(b"Hello World") f.write(b"Hello World")
Dopo l’esecuzione verrà creato un file chiamato test.dat
, contenente 3x Hello World
. I dati non saranno tenuti in memoria dopo essere stati scritti nel file (a meno che non siano tenuti da un nome).
Ora se considerate io.BytesIO()
invece:
with io.BytesIO() as f: f.write(b"Hello World") f.write(b"Hello World") f.write(b"Hello World")
che invece di scrivere il contenuto in un file, viene scritto in un buffer di memoria. In altre parole un pezzo di RAM. Essenzialmente scrivere quanto segue sarebbe l’equivalente:
buffer = b""buffer += b"Hello World"buffer += b"Hello World"buffer += b"Hello World"
In relazione all’esempio con l’istruzione with, alla fine ci sarebbe anche un del buffer
.
La differenza chiave qui è l’ottimizzazione e le prestazioni. io.BytesIO
è in grado di fare alcune ottimizzazioni che lo rendono più veloce della semplice concatenazione di tutti i b"Hello World"
uno per uno.
Solo per provarlo ecco un piccolo benchmark:
- Concat: 1.3529 secondi
- BytesIO: 0.0090 secondi
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)
Oltre al guadagno di prestazioni, usare BytesIO
invece di concatenare ha il vantaggio che BytesIO
può essere usato al posto di un oggetto file. Quindi diciamo che avete una funzione che si aspetta un oggetto file su cui scrivere. Allora potete dargli quel buffer in-memory invece di un file.
La differenza è che open("myfile.jpg", "rb")
semplicemente carica e restituisce il contenuto di myfile.jpg
; mentre, BytesIO
di nuovo è solo un buffer contenente alcuni dati.
Siccome BytesIO
è solo un buffer – se volete scrivere il contenuto in un file in seguito – dovrete fare:
buffer = io.BytesIO()# ...with open("test.dat", "wb") as f: f.write(buffer.getvalue())
Inoltre, non avete menzionato una versione; io sto usando Python 3. Relativo agli esempi: Sto usando l’istruzione with invece di chiamare f.close()