J'essaie de comprendre les méthodes write () et read () de io.BytesIO. Ma compréhension était que je pouvais utiliser le io.BytesIO comme j'utiliserais un objet File.
import io
in_memory = io.BytesIO(b'hello')
print( in_memory.read() )
Le code ci-dessus renverra b'hello ' comme prévu, mais le code ci-dessous renverra une chaîne vide b' ".
import io
in_memory = io.BytesIO(b'hello')
in_memory.write(b' world')
print( in_memory.read() )
Mes questions sont:
-Que fait io.BytesIO.write(b' world')
exactement?
-Quelle est la différence entre io.BytesIO.read () et io.BytesIO.getvalue ()?
Je suppose que la réponse est liée à io.BytesIO étant un objet de flux, mais la vue d'ensemble n'est pas claire pour moi.
Le problème est que vous êtes positionné à la fin du flux. Pensez à la position comme un curseur. Une fois que vous avez écrit b' world'
, Votre curseur se trouve à la fin du flux. Lorsque vous essayez de .read()
, vous lisez tout après la position du curseur - qui n'est rien, donc vous obtenez la chaîne de bytest vide.
Pour naviguer dans le flux, vous pouvez utiliser la méthode .seek
:
>>> import io
>>> in_memory = io.BytesIO(b'hello', )
>>> in_memory.write(b' world')
>>> in_memory.seek(0) # go to the start of the stream
>>> print(in_memory.read())
b' world'
Notez que, tout comme un flux de fichiers en mode write
('w'
), Les octets initiaux b'hello'
Ont été écrasés par votre écriture de b' world'
.
.getvalue()
renvoie simplement le contenu entier du flux quelle que soit la position actuelle.
c'est un flux mémoire mais toujours un flux. La position est stockée, donc comme tout autre flux si vous essayez de lire après avoir écrit, vous devez repositionner:
import io
in_memory = io.BytesIO(b'hello')
in_memory.seek(0,2) # seek to end, else we overwrite
in_memory.write(b' world')
in_memory.seek(0) # seek to start
print( in_memory.read() )
impressions:
b'hello world'
tandis que in_memory.getvalue()
n'a pas besoin de la dernière seek(0)
car elle renvoie le contenu du flux à partir de la position 0.
BytesIO
se comporte comme un fichier, un seul que vous pouvez à la fois lire et écrire. La partie déroutante, peut-être, est que la position de lecture et d'écriture est la même. Alors d'abord vous faites:
in_memory = io.BytesIO(b'hello')
Cela vous donne un tampon d'octets dans in_memory
Avec le contenu b'hello'
Et avec la position de lecture/écriture au début (avant le premier b'h'
). Quand vous faites:
in_memory.write(b' world')
Vous écrasez effectivement b'hello'
Avec b' world'
(Et obtenez en fait un octet de plus), et maintenant vous avez la position à la fin (après le dernier b'd'
). Donc, quand vous le faites:
print( in_memory.read() )
Vous ne voyez rien car il n'y a rien à lire après la position actuelle. Vous pouvez cependant utiliser seek
pour déplacer la position, donc si vous le faites
import io
in_memory = io.BytesIO(b'hello')
in_memory.write(b' world')
in_memory.seek(0)
print( in_memory.read() )
Vous obtenez:
b' world'
Notez que vous ne voyez pas le b'hello'
Initial car il a été remplacé. Si vous souhaitez écrire après le contenu initial, vous pouvez d'abord rechercher jusqu'à la fin:
import io
in_memory = io.BytesIO(b'hello')
in_memory.seek(0, 2)
in_memory.write(b' world')
in_memory.seek(0)
print( in_memory.read() )
Production:
b'hello world'
EDIT: À propos de getvalue
, comme indiqué par d'autres réponses, il vous donne le tampon interne complet, indépendamment de la position actuelle. Cette opération n'est évidemment pas disponible pour les fichiers.