2013-04-01 9 views
13

Gibt es einen guten Grund, warum ich alle meine Python-Programme damit nicht starten sollte? Gibt es etwas Besonderes verloren, wenn man so etwas macht?Stdout-Codierung in Python

#!/usr/bin/python 
import os, sys 
if sys.stdout.encoding == None: 
    os.putenv("PYTHONIOENCODING",'UTF-8') 
    os.execv(sys.executable,['python']+sys.argv) 
print sys.stdout.encoding 

Es gibt 60 questions about PYTHONIOENCODING also denke ich, es ist ein weit verbreitetes Problem ist, aber falls Sie nicht wissen, ist dies, weil getan, wenn sys.stdout.encoding == None dann können Sie nur Zeichen Druck ascii, so z.B. print "åäö" wirft eine Ausnahme ..

EDIT Dies passiert mir, wenn Stdout eine Pfeife ist; python encoding.py|cat setzt die Codierung auf Keine

Eine andere Lösung ist, die codec of stdoutsys.stdout = codecs.getwriter('utf8')(sys.stdout) zu ändern, die ich vermute, ist die richtige Antwort trotz der Kommentare zu dieser Frage.

+0

Welche Plattform ist das, BTW? Nur aus Interesse. –

+0

Siehe auch http://stackoverflow.com/questions/1473577/writing-unicode-strings-via-sys-stdout-in-python – Michael

+3

Was * ist * stdout in diesen Fällen? Ein Rohr? Woher weißt du, dass, was auch immer das Rohr verbindet, UTF8 unterstützen kann? Es ist die Aufgabe von allem, was die Pipe anstellt, in diesem Fall 'PYTHONIOENCODING' zu spezifizieren. –

Antwort

8

Ja, es gibt einen guten Grund, nicht alle Ihre Python-Programme so zu starten.

Zu allererst:

sys.stdout.encoding ist None, wenn Python nicht weiß, was die stdout unterstützt kodieren. Dies ist in den meisten Fällen, weil es überhaupt keine Codierung unterstützt. In Ihrem Fall liegt das daran, dass es sich beim stdout um eine Datei und nicht um ein Terminal handelt. Aber es könnte auf None gesetzt werden, da Python auch die Kodierung des Terminals nicht erkennt.

Zweitens: Sie setzen die Umgebungsvariable und starten dann einen neuen Prozess mit dem Befehl smae erneut. Das ist ziemlich hässlich.

Also, wenn Sie nicht planen, der einzige zu sein, der Ihre Programme verwendet, sollten Sie sie nicht so starten. Aber wenn Sie tun planen, die einzige, die Ihr Programm verwenden, dann gehen Sie voran.

mehr in die Tiefe gehende Erklärung

Eine bessere generische Lösung unter Python 2 ist stdout so zu behandeln, was es ist: Ein 8-Bit-Schnittstelle. Und das bedeutet, dass alles, was Sie auf stdout drucken, 8-Bit sein soll. Sie erhalten den Fehler, wenn Sie versuchen, Unicode-Daten zu drucken, da print dann versuchen wird, die Unicode-Daten in die Codierung von stdout zu codieren, und wenn es keine ist, nimmt es ASCII an und schlägt fehl, es sei denn, Sie setzen PYTHONIOENCODING.

Aber durch das Drucken von codierten Daten haben Sie dieses Problem nicht. Die folgenden funktioniert perfekt, auch wenn der Ausgang geleitet wird:

print u'ÅÄÖ'.encode('UTF8') 

(Dies wird jedoch unter Python scheitern 3, weil unter Python 3, stdout ist nicht mehr 8-Bit-IO, sollen Sie es Unicode-Daten geben, , und es wird von selbst kodieren. Wenn Sie es Binärdaten geben, wird es die Darstellung drucken. Daher auf Python 3 haben Sie dieses Problem an erster Stelle nicht).

+0

Warum ist es eine schlechte Idee, Sie erwähnen das nicht wirklich ... Was ist schlimmer, keine Daten von einem Programm zu bekommen, oder es in der falschen Kodierung bekommen? Mein Problem ist, dass dies von ~ 20 Leuten ausgeführt wird und ich muss ihnen sagen, dass sie PYTHONIOENCODING einstellen sollen, also ist dies ein vernünftiger Standard. –

+0

@ErikJohansson: Es ist schlimmer, es in der falschen Codierung zu bekommen. Andernfalls erhalten Sie einen Fehler, den Sie beheben können. Es gibt keinen Grund für dich, PYTHONIOENCODING zu setzen, der Fehler ist woanders. –

+0

@Lennart_Rebebro: Nein, während ich zustimme, dass exec eine hässliche Lösung ist, default zu etwas, das als Ausgangskodierung verwendbar nicht falsch ist. Eine Anwendung muss in der Lage sein, Daten zur Arbeit auszugeben. –