Différence entre `open` et `io.BytesIO` dans les flux binaires
Pour simplifier, considérons l’écriture au lieu de la lecture pour le moment.
Donc, lorsque vous utilisez open()
comme disons :
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é cela, un fichier appelé test.dat
sera créé, contenant 3x Hello World
. Les données ne seront pas conservées en mémoire après avoir été écrites dans le fichier (sauf si elles sont conservées par un nom).
Maintenant, lorsque 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")
Qu’au lieu d’écrire le contenu dans un fichier, il est écrit dans un tampon en mémoire. 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 with, alors à la fin il y aurait aussi un del buffer
.
La différence clé ici est l’optimisation et la performance. io.BytesIO
est capable d’effectuer certaines optimisations qui le rendent plus rapide que la simple concaténation de tous les b"Hello World"
un par un.
Pour le prouver, voici un petit benchmark:
- Concat : 1,3529 secondes
- BytesIO : 0.0090 secondes
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)
En dehors du gain de performance, l’utilisation de BytesIO
au lieu de la concaténation a l’avantage que BytesIO
peut être utilisé à la place d’un objet fichier. Ainsi, disons que vous avez une fonction qui attend un objet fichier pour y écrire. Alors vous pouvez lui donner ce tampon en mémoire au lieu d’un fichier.
La différence est que open("myfile.jpg", "rb")
charge et renvoie simplement le contenu de myfile.jpg
; alors que, BytesIO
encore une fois, c’est juste un tampon contenant quelques données.
Puisque BytesIO
est juste un tampon – si vous vouliez écrire le contenu dans un fichier plus tard – vous devriez faire :
buffer = io.BytesIO()# ...with open("test.dat", "wb") as f: f.write(buffer.getvalue())
En outre, vous n’avez pas mentionné de version ; j’utilise Python 3. En rapport avec les exemples : J’utilise l’instruction with au lieu d’appeler f.close()
.