Różnica między `open` i `io.BytesIO` w strumieniach binarnych
Dla uproszczenia, rozważmy teraz pisanie zamiast czytania.
Więc kiedy używasz open()
jak powiedzmy:
with open("test.dat", "wb") as f: f.write(b"Hello World") f.write(b"Hello World") f.write(b"Hello World")
Po wykonaniu tego polecenia zostanie utworzony plik o nazwie test.dat
, zawierający 3x Hello World
. Dane nie będą przechowywane w pamięci po zapisaniu ich do pliku (chyba, że będą przechowywane przez nazwę).
Teraz, gdy rozważysz io.BytesIO()
zamiast:
with io.BytesIO() as f: f.write(b"Hello World") f.write(b"Hello World") f.write(b"Hello World")
Który zamiast zapisywać zawartość do pliku, jest zapisywany do bufora w pamięci. Innymi słowy do kawałka pamięci RAM. Zasadniczo napisanie poniższego byłoby odpowiednikiem:
buffer = b""buffer += b"Hello World"buffer += b"Hello World"buffer += b"Hello World"
W odniesieniu do przykładu z instrukcją with, to na końcu również byłoby del buffer
.
Kluczową różnicą jest tutaj optymalizacja i wydajność. io.BytesIO
jest w stanie wykonać pewne optymalizacje, które sprawiają, że jest szybszy niż po prostu konkatenacja wszystkich b"Hello World"
jeden po drugim.
Gdyby to udowodnić, oto mały benchmark:
- Concat: 1.3529 sekundy
- BytesIO: 0.0090 sekund
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)
Poza wzrostem wydajności, używanie BytesIO
zamiast konkatenacji ma tę zaletę, że BytesIO
może być używany w miejsce obiektu pliku. Więc powiedzmy, że masz funkcję, która oczekuje obiektu pliku do zapisu. Następnie możesz dać mu ten bufor w pamięci zamiast pliku.
Różnica polega na tym, że open("myfile.jpg", "rb")
po prostu ładuje i zwraca zawartość myfile.jpg
; podczas gdy BytesIO
ponownie jest po prostu buforem zawierającym pewne dane.
Ponieważ BytesIO
jest tylko buforem – gdybyś chciał później zapisać jego zawartość do pliku – musiałbyś zrobić:
buffer = io.BytesIO()# ...with open("test.dat", "wb") as f: f.write(buffer.getvalue())
Nie wspomniałeś też o wersji; używam Pythona 3. Odnosząc się do przykładów: Używam instrukcji with zamiast wywoływania f.close()