Python: Comment faire pour que StringIO.writelines accepte les chaînes unicode?
Question
Je reçois un
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 34: ordinal not in range(128)
sur une chaîne stockée dans 'a.desc' ci-dessous car elle contient le caractère '£'. Elle est stockée dans la banque de données Google App Engine sous-jacente sous forme de chaîne Unicode, ce qui convient parfaitement. La fonction cStringIO.StringIO.writelines tente apparemment de l'encoder au format ascii:
result.writelines(['blahblah',a.desc,'blahblahblah'])
Comment lui demander de traiter le codage comme unicode si c'est le phrasé correct?
Le moteur d'application fonctionne sur Python 2.5
La solution
Contrairement aux fichiers de mémoire implémentés par le module StringIO, ceux fournis par [cStringIO] ne peuvent pas accepter les chaînes Unicode qui ne peuvent pas être codées sous forme de chaînes ASCII ordinaires.
Si possible, utilisez StringIO au lieu de cStringIO.
Autres conseils
Vous pouvez envelopper l'objet StringIO dans un objet codecs.StreamReaderWriter
pour encoder et décoder automatiquement unicode.
Comme ceci:
import cStringIO, codecs
buffer = cStringIO.StringIO()
codecinfo = codecs.lookup("utf8")
wrapper = codecs.StreamReaderWriter(buffer,
codecinfo.streamreader, codecinfo.streamwriter)
wrapper.writelines([u"list of", u"unicode strings"])
tampon
sera rempli d'octets codés en utf-8.
Si je comprends bien votre cas, il vous suffira d'écrire pour pouvoir aussi:
import cStringIO, codecs
buffer = cStringIO.StringIO()
wrapper = codecs.getwriter("utf8")(buffer)
Vous pouvez également coder votre chaîne manuellement en tant que utf-8 avant de l'ajouter à StringIO
for val in rows:
if isinstance(val, unicode):
val = val.encode('utf-8')
result.writelines(rows)
Python 2.6 a introduit le module io
et vous devriez envisager d'utiliser io.StringIO ()
, "Un flux en mémoire pour le texte Unicode."
Dans les anciennes versions de Python, cela n’était pas optimisé (pur Python). Dans les versions ultérieures, cela a été optimisé pour le code C. (rapide).