Unterschied zwischen `open` und `io.BytesIO` in binären Strömen
Der Einfachheit halber betrachten wir vorerst das Schreiben statt das Lesen.
Wenn Sie also open()
wie sagen:
with open("test.dat", "wb") as f: f.write(b"Hello World") f.write(b"Hello World") f.write(b"Hello World")
Nach der Ausführung wird eine Datei namens test.dat
erstellt, die 3x Hello World
enthält. Die Daten werden nicht im Speicher gehalten, nachdem sie in die Datei geschrieben wurden (es sei denn, sie werden durch einen Namen gehalten).
Nun, wenn Sie stattdessen io.BytesIO()
betrachten:
with io.BytesIO() as f: f.write(b"Hello World") f.write(b"Hello World") f.write(b"Hello World")
Der Inhalt wird nicht in eine Datei, sondern in einen Puffer im Speicher geschrieben. Mit anderen Worten, in einen Teil des RAM. Im Wesentlichen wäre das Schreiben des Folgenden das Äquivalent:
buffer = b""buffer += b"Hello World"buffer += b"Hello World"buffer += b"Hello World"
Bezogen auf das Beispiel mit der with-Anweisung würde dann am Ende auch ein del buffer
stehen.
Der entscheidende Unterschied ist hier die Optimierung und die Performance. Das io.BytesIO
ist in der Lage, einige Optimierungen vorzunehmen, die es schneller machen als die einfache Verkettung aller b"Hello World"
nacheinander.
Zum Beweis hier ein kleiner Benchmark:
- Concat: 1,3529 Sekunden
- BytesIO: 0.0090 Sekunden
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)
Neben dem Performancegewinn hat die Verwendung von BytesIO
anstelle der Verkettung den Vorteil, dass BytesIO
anstelle eines Dateiobjekts verwendet werden kann. Sagen wir also, Sie haben eine Funktion, die ein Dateiobjekt zum Schreiben erwartet.
Der Unterschied ist, dass open("myfile.jpg", "rb")
einfach den Inhalt von myfile.jpg
lädt und zurückgibt, während BytesIO
wiederum nur ein Puffer ist, der einige Daten enthält.
Da BytesIO
nur ein Puffer ist – wenn Sie den Inhalt später in eine Datei schreiben wollten – müssten Sie folgendes tun:
buffer = io.BytesIO()# ...with open("test.dat", "wb") as f: f.write(buffer.getvalue())
Auch haben Sie keine Version erwähnt; ich verwende Python 3. Bezogen auf die Beispiele: Ich verwende die with-Anweisung statt des Aufrufs f.close()