web-dev-qa-db-fra.com

Remplacement de StringIO qui fonctionne avec des octets au lieu de chaînes?

Existe-t-il un remplacement pour la classe python StringIO, qui fonctionnera avec bytes au lieu des chaînes?

Cela peut ne pas être évident, mais si vous avez utilisé StringIO pour traiter des données binaires, vous n'avez pas de chance avec Python 2.7 ou plus récent.

60
sorin

Essayez io.BytesIO .

Comme autresont souligné, vous pouvez en effet utiliser StringIO en 2.7, mais BytesIO est un bon choix pour la compatibilité ascendante.

103
senderle

Dans Python 2.6/2.7, le module io est destiné à être utilisé pour la compatibilité avec Python 3.X. À partir de la documentation) :

Nouveau dans la version 2.6.

Le module io fournit les interfaces Python pour la gestion des flux. Sous Python 2.x, ceci est proposé comme une alternative à l'objet fichier intégré, mais dans Python 3.x c'est l'interface par défaut pour accéder aux fichiers et aux flux.

Remarque Étant donné que ce module a été conçu principalement pour Python 3.x, vous devez être conscient que toutes les utilisations des "octets" dans ce document se réfèrent au type str (dont les octets sont un alias). ), et toutes les utilisations de "texte" se réfèrent au type unicode. De plus, ces deux types ne sont pas interchangeables dans les API io.

Dans Python versions antérieures à 3.X le module StringIO contient la version héritée de StringIO, qui contrairement à io.StringIO peut être utilisé dans les versions antérieures à 2.6 de Python:

>>> import StringIO
>>> s=StringIO.StringIO()
>>> s.write('hello')
>>> s.getvalue()
'hello'
>>> import io
>>> s=io.StringIO()
>>> s.write('hello')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: string argument expected, got 'str'
>>> s.write(u'hello')
5L
>>> s.getvalue()
u'hello'
10
Mark Tolonen

Vous dites: " Ce n'est peut-être pas évident mais si vous avez utilisé StringIO pour traiter des données binaires, vous n'avez pas de chance avec Python 2.7 ou plus récent".

Ce n'est pas évident parce que ce n'est pas vrai.

Si vous avez du code qui fonctionne sur 2.6 ou version antérieure, il continue de fonctionner sur 2.7 . Vidage d'écran non modifié (habillage de fenêtre d'invite de commandes Windows au col 80 et tout):

C:\Users\John>\python26\python -c"import sys,StringIO;s=StringIO.StringIO();s.wr
ite('hello\n');print repr(s.getvalue()), sys.version"
'hello\n' 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)]

C:\Users\John>\python27\python -c"import sys,StringIO;s=StringIO.StringIO();s.wr
ite('hello\n');print repr(s.getvalue()), sys.version"
'hello\n' 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)]

Si vous devez écrire du code qui s'exécute sur 2.7 et 3.x, utilisez la classe BytesIO dans le module io.

Si vous avez besoin/voulez une base de code unique qui prend en charge 2.7, 2.6, ... et 3.x, vous devrez travailler un peu plus. Utilisation le module six devrait aider beaucoup.

7
John Machin