Articles

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()

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *