9 votes

différences de gestion de l'unicode en python entre print et sys.stdout.write

Je commencerai par dire que j'ai déjà vu ce billet : Comportement étrange de l'impression en python avec l'unicode mais la solution proposée (utiliser PYTHONIOENCODING) n'a pas fonctionné pour moi.

Voici mon problème :

Python 2.6.5 (r265:79063, Apr  9 2010, 11:16:46)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
>>> a = u'\xa6'
>>> print a 
¦

fonctionne cependant très bien :

>>> sys.stdout.write(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa6' in position 0: ordinal not in range(128)

provoque une erreur. L'article que j'ai linké en haut suggère que c'est parce que l'encodage par défaut de la console est 'ascii'. Cependant, dans mon cas, ce n'est pas le cas :

>>> sys.stdout.encoding
'UTF-8'

Avez-vous des idées sur ce qui se passe ici et sur la manière de résoudre ce problème ?

Remerciements D.

12voto

ekhumoro Points 23190

Ceci est dû à un bogue de longue date qui a été fixe dans python-2.7, mais trop tard pour être rétroporté dans python-2.6.

La documentation indique que lorsque des chaînes unicode sont écrites dans un fichier, elles doivent être converties en chaînes d'octets à l'aide de la fonction fichier.encodage . Mais cela n'était pas respecté par sys.stdout, qui utilisait à la place l'encodage unicode par défaut. Celui-ci est généralement défini à "ascii" par la commande site mais il peut être modifié à l'aide du module sys.setdefaultencoding :

Python 2.6.7 (r267:88850, Aug 14 2011, 12:32:40) [GCC 4.6.2] on linux3
>>> a = u'\xa6\n'
>>> sys.stdout.write(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec cant encode character u'\xa6' ...
>>> reload(sys).setdefaultencoding('utf8')
>>> sys.stdout.write(a)
¦

Toutefois, une meilleure solution consisterait à remplacer sys.stdout avec un emballage :

class StdOut(object):
    def write(self, string):
        if isinstance(string, unicode):
            string = string.encode(sys.__stdout__.encoding)
        sys.__stdout__.write(string)

>>> sys.stdout = StdOut()
>>> sys.stdout.write(a)
¦

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