2009-09-24 8 views
16

Supposons un instant que l'on ne puisse pas utiliser print (et donc profiter des avantages de la détection automatique d'encodage). Donc, cela nous laisse avec sys.stdout. Cependant, sys.stdout est tellement bête au not do any sensible encoding.Ecriture de chaînes Unicode via sys.stdout en Python

Maintenant, on lit la page wiki Python PrintFails et va essayer le code suivant:

$ python -c 'import sys, codecs, locale; print str(sys.stdout.encoding); \ 
    sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); 

Toutefois, cela ne fonctionne pas trop (au moins sur Mac). Trop voir pourquoi:

>>> import locale 
>>> locale.getpreferredencoding() 
'mac-roman' 
>>> sys.stdout.encoding 
'UTF-8' 

(UTF-8 est ce que le terminal comprend).

Donc, on modifie le code ci-dessus:

$ python -c 'import sys, codecs, locale; print str(sys.stdout.encoding); \ 
    sys.stdout = codecs.getwriter(sys.stdout.encoding)(sys.stdout); 

Et maintenant les chaînes unicode sont correctement envoyés à sys.stdout et, par conséquent imprimer correctement sur le terminal (sys.stdout est attaché le terminal).

Est-ce la bonne façon d'écrire des chaînes Unicode dans sys.stdout ou devrais-je faire autre chose?

EDIT: parfois - par exemple, lorsque vous redirigez la sortie less - sys.stdout.encoding sera None. dans ce cas, le code ci-dessus échouera.

+0

s/my/sa/pour la cohérence – icedwater

Répondre

3

Je ne comprends pas pourquoi vous ne seriez pas capable d'imprimer; mais en supposant que oui, l'approche me semble juste.

+1

Une raison pour laquelle je ne peux pas utiliser 'print' est d'éviter que l'espace supplémentaire' print' imprime. Regardez l'utilisation de 'sys.stdout' ici: http://stackoverflow.com/questions/1396820/apt-like-column-output-python-library/1397382#1397382 –

+3

Vous pouvez créer des lignes complètes, puis imprimer leur. –

+0

Bravo! Oui, dans ce cas, je peux utiliser 'print' –

10

La meilleure idée est de vérifier si vous êtes directement connecté à un terminal. Si c'est le cas, utilisez l'encodage du terminal. Sinon, utilisez le codage préféré du système.

if sys.stdout.isatty(): 
    default_encoding = sys.stdout.encoding 
else: 
    default_encoding = locale.getpreferredencoding() 

Il est également très important de toujours permettre à l'utilisateur de spécifier l'encodage qu'elle souhaite. Habituellement, je le fais une option de ligne de commande (comme -e ENCODING), et l'analyser avec le module optparse.

Une autre bonne chose est de pas remplacer sys.stdout avec un encodeur automatique. Créez votre encodeur et utilisez-le, mais laissez sys.stdout seul. Vous pouvez importer directement des bibliothèques tierces qui écrivent des chaînes codées codées à sys.stdout.

8

Il existe une variable d'environnement facultative "PYTHONIOENCODING" qui peut être définie sur un codage par défaut souhaité. Ce serait une façon de saisir l'encodage souhaité par l'utilisateur d'une manière cohérente avec tout Python. Il est enterré dans le manuel Python here.

27
export PYTHONIOENCODING=utf-8 

fera le travail, mais ne peut pas le configurer sur python lui-même ...

ce que nous pouvons faire est de vérifier si ne fixe pas de dire à l'utilisateur de le mettre avant le script d'appel avec:

if __name__ == '__main__': 
    if (sys.stdout.encoding is None): 
     print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout." 
     exit(1) 
+0

Merci beaucoup, travaille pour moi. – Kino

6

C'est ce que je fais dans ma demande:

sys.stdout.write(s.encode('utf-8'))

C'est le correctif exactement inverse pour la lecture des noms de caractères UTF-8 de argv:

for file in sys.argv[1:]: 
    file = file.decode('utf-8') 

Ceci est très moche (IMHO) car il vous force à travailler avec UTF-8 .. qui est la norme sur Linux/Mac, mais pas sur Windows ... Fonctionne pour moi de toute façon :)

Questions connexes