Différence entre` open `et ' io.BytesIO` dans les flux binaires

j'apprends à travailler avec streams en Python et j'ai remarqué que le IO docs dire la chose suivante:

la façon la plus simple de créer un flux binaire est avec open () avec 'b' dans la chaîne de mode:

f = open("myfile.jpg", "rb")

les flux binaires en mémoire sont également disponibles sous forme D'objets BytesIO:

f = io.BytesIO(b"some initial binary data: x00x01")

Quelle est la différence entre f comme défini par open et f comme défini par BytesIO. En d'autres termes, ce qui rend un "flux binaire en mémoire" et comment est-ce différent de ce que open?

21
demandé sur Luke Whyte 2017-03-15 05:49:27

3 réponses

pour des raisons de simplicité, envisageons d'écrire plutôt que de lire pour l'instant.

donc quand vous utilisez open() comme par exemple:

with open("test.dat", "wb") as f:
    f.write(b"Hello World")
    f.write(b"Hello World")
    f.write(b"Hello World")

après avoir exécuté ce fichier appelé test.dat sera créé, contenant Hello World. Les données ne seront pas conservées en mémoire après avoir été écrites dans le fichier (à moins d'être conservées par un nom).

Maintenant, quand vous considérez io.BytesIO() au lieu de:

with io.BytesIO() as f:
    f.write(b"Hello World")
    f.write(b"Hello World")
    f.write(b"Hello World")

Qui, au lieu d'écrire le contenu d'un fichier, il est écrit dans un dans la mémoire tampon. En d'autres termes, un morceau de RAM. Essentiellement, écrire ce qui suit serait l'équivalent:

buffer = b""
buffer += b"Hello World"
buffer += b"Hello World"
buffer += b"Hello World"

par rapport à l'exemple avec l'instruction, puis à la fin il y aurait aussi un del buffer.

la différence clé ici est l'optimisation et la performance. io.BytesIO est capable de faire quelques optimisations qui le rendent plus rapide que de simplement concaténer tous les b"Hello World" un par un.

Juste pour le prouver, voici une petit indice:

  • Concat: 1.3529 secondes
  • BytesIO: 0.0090 seconds

import io
import time

begin = time.time()
buffer = b""
for i in range(0, 50000):
    buffer += b"Hello World"
end = time.time()
seconds = end - begin
print("Concat:", seconds)

begin = time.time()
buffer = io.BytesIO()
for i in range(0, 50000):
    buffer.write(b"Hello World")
end = time.time()
seconds = end - begin
print("BytesIO:", seconds)

outre le gain de performance, en utilisant BytesIO au lieu de concaténer a l'avantage d' BytesIO peut être utilisé à la place d'un fichier objet. Donc, disons que vous avez une fonction qui attend un objet fichier à écrire. Ensuite, vous pouvez lui donner un tampon en mémoire au lieu d'un fichier.

La différence est que open("myfile.jpg", "rb") simplement les charges et retourne le contenu de myfile.jpg; attendu que, BytesIO encore une fois est juste un tampon contenant quelques données.

Depuis BytesIO est juste un tampon - si vous souhaitez écrire le contenu d'un fichier plus tard - que vous avez à faire:

buffer = io.BytesIO()
# ...
with open("test.dat", "wb") as f:
    f.write(buffer.getvalue())

en outre, vous n'avez pas mentionné une version; J'utilise Python 3. En rapport avec les exemples: j'utilise l'instruction with au lieu d'appeler f.close()

32
répondu Vallentin 2018-09-24 16:46:14

en utilisant open ouvre un fichier sur votre disque dur. Selon le mode que vous utilisez, vous pouvez lire ou écrire (ou les deux) à partir du disque.

BytesIO objet n'est pas associé à un fichier sur le disque. C'est juste un morceau de mémoire qui se comporte comme un fichier. Il a la même API qu'un objet de fichier retourné de open (avec le mode r+b, permettant la lecture et l'écriture de données binaires).

BytesIO (et il est proche de la fratrie StringIO qui est toujours en mode texte) peut être utile lorsque vous avez besoin de passer des données à ou à partir d'une API qui s'attendent à recevoir un objet de fichier, mais où vous préférez passer les données directement. Vous pouvez charger vos données que vous avez dans le BytesIO avant de la donner à la bibliothèque. Après qu'il retourne, vous pouvez obtenir toutes les données que la bibliothèque a écrites dans le fichier à partir de BytesIOgetvalue() méthode. (Généralement vous ne devez le faire un de ces, bien sûr.)

6
répondu Blckknght 2017-03-15 03:31:35
f = open("myfile.jpg", "rb")

lire les octets du fichier à partir du disque dur et attribuer une telle valeur à l'objet référencé comme 'f' qui est conservé par Python en mémoire.

f = io.BytesIO(b"some initial binary data: \x00\x01")

Assignez une valeur de flux d'octets à un objet référencé comme 'f' qui est conservé par Python en mémoire.

0
répondu BlueTomato 2018-02-22 10:20:49