111 votes

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

Je suis en train d'apprendre sur le travail avec les flux en Python et j'ai remarqué que le IO docs dire la chose suivante:

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

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

En mémoire les flux binaires sont également disponibles comme BytesIO objets:

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

Quelle est la différence entre f tel que défini par open et f tel que défini par BytesIO. En d'autres termes, ce qui fait une "en mémoire Dans le flux binaire" et comment est-ce différent de ce que l' open n'?

148voto

Vallentin Points 2974

Par souci de simplicité, nous allons envisager d'écrire au lieu de lire pour l'instant.

Ainsi, lorsque vous utilisez open() comme le disent:

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

Après l'exécution d'un fichier appelé test.dat sera créé, contenant Hello World. Les données ne seront pas conservées en mémoire une fois que c'est écrit dans le fichier (à moins d'être gardé par un nom).

Maintenant, quand vous considérez io.BytesIO() à la place:

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 une mémoire tampon. En d'autres termes, une partie de la RAM. Essentiellement de l'écriture de la suite 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 principale différence ici est de l'optimisation et de la performance. io.BytesIO est capable de faire quelques optimisations qui le rend plus rapide que de simplement la concaténation de tous les b"Hello World" , un par un.

Juste pour le prouver, voici un petit indice:

  • Concat: 1.3529 secondes
  • BytesIO: 0.0090 secondes

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, à l'aide de 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 charges et retourne le contenu de l' myfile.jpg; considérant que, BytesIO nouveau est à seulement un tampon contenant des données.

Depuis BytesIO est à seulement 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())

Aussi, vous n'avez pas mentionné une version; je suis à l'aide de Python 3. Liées à la exemples: je suis l'aide de la déclaration au lieu de l'appeler f.close()

22voto

Blckknght Points 20780

À l'aide de 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.

Un BytesIO objet n'est pas associé à un fichier sur le disque. C'est juste une partie de la mémoire qui se comporte comme un fichier ne. Il a la même API que un fichier objet retourné à partir de open (avec mode d' 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 transmettre des données vers ou à partir d'une API qui s'attendent à être donné un fichier objet, mais l'endroit où vous préférez passer directement les données. Vous pouvez charger vos données d'entrée en BytesIO avant de la donner à la bibliothèque. Après son retour, vous pouvez obtenir toutes les données de la bibliothèque a écrit dans le fichier de l' BytesIO à l'aide de l' getvalue() méthode. (Généralement vous ne devez le faire un de ces, bien sûr.)

-5voto

BlueTomato Points 711
 f = open("myfile.jpg", "rb")
 

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

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X