Wenn die Ausgabe eines Python-Programms weitergeleitet wird, ist der Python-Interpreter verwirrt über die Codierung und setzt sie auf Keine. Dies bedeutet ein Programm wie dieses:
# -*- coding: utf-8 -*-
print u"åäö"
funktioniert bei normaler Ausführung einwandfrei, schlägt jedoch fehl mit:
UnicodeEncodeError: Der Codec 'ascii' kann das Zeichen u '\ xa0' an Position 0 nicht codieren: Ordnungszahl nicht im Bereich (128)
bei Verwendung in einer Rohrfolge.
Was ist der beste Weg, um diese Arbeit beim Verrohren zu machen? Kann ich ihm einfach sagen, dass er die Codierung verwenden soll, die die Shell / das Dateisystem / was auch immer verwendet?
Die Vorschläge, die ich bisher gesehen habe, sind, Ihre site.py direkt zu ändern oder die Defaultencodierung mit diesem Hack fest zu codieren:
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"
Gibt es einen besseren Weg, um Rohrleitungen zum Laufen zu bringen?
chcp 65001
bevor Sie Ihr Skript ausführen. Dies kann Probleme haben, hilft aber oft und erfordert nicht viel Tippen (weniger alsset PYTHONIOENCODING=utf_8
).setx PYTHONENCODING utf-8
, es dauerhaft zu machen, wenn Sie die Eingabe speichern möchten.Antworten:
Ihr Code funktioniert, wenn er in einem Skript ausgeführt wird, da Python die Ausgabe in die von Ihrer Terminalanwendung verwendete Codierung codiert. Wenn Sie Rohrleitungen verwenden, müssen Sie diese selbst codieren.
Als Faustregel gilt: Verwenden Sie Unicode immer intern. Dekodieren Sie, was Sie empfangen, und kodieren Sie, was Sie senden.
Ein weiteres didaktisches Beispiel ist ein Python-Programm zum Konvertieren zwischen ISO-8859-1 und UTF-8, bei dem alles dazwischen in Großbuchstaben geschrieben wird.
Das Festlegen der Standardcodierung des Systems ist eine schlechte Idee, da einige von Ihnen verwendete Module und Bibliotheken sich darauf verlassen können, dass es sich um ASCII handelt. Tu es nicht.
quelle
sys.stdout
scheint ein angenehmerer Weg zu sein.PYTHONIOENCODING
Sie , wenn Sie die Standardausgabe des Skripts in Python 2 umleiten.Zunächst zu dieser Lösung:
Es ist nicht praktisch, jedes Mal explizit mit einer bestimmten Codierung zu drucken. Das wäre repetitiv und fehleranfällig.
Eine bessere Lösung besteht darin,
sys.stdout
zu Beginn Ihres Programms zu ändern und mit einer ausgewählten Codierung zu codieren. Hier ist eine Lösung, die ich in Python gefunden habe: Wie wird sys.stdout.encoding ausgewählt? , insbesondere ein Kommentar von "toka":quelle
def myprint(unicodeobj): print unicodeobj.encode('utf-8')
- Sie erkennen die Terminalcodierung automatisch durch Inspektionsys.stdout.encoding
, sollten jedoch den Fall berücksichtigen, in dem sie sich befindetNone
(dh wenn Sie die Ausgabe in eine Datei umleiten). Sie benötigen also ohnehin eine separate Funktion.Möglicherweise möchten Sie versuchen, die Umgebungsvariable "PYTHONIOENCODING" in "utf_8" zu ändern. Ich habe eine Seite über meine Tortur mit diesem Problem geschrieben .
Tl; dr des Blogposts:
gibt Ihnen
quelle
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
. Dies kann innerhalb des Python-Programms erfolgen, sodass der Benutzer nicht gezwungen ist, eine env-Variable festzulegen.PYTHONIOENCODING
funktioniert. Wie Bytes als Text interpretiert werden, wird von der Benutzerumgebung definiert . Ihr Skript sollte nicht davon ausgehen und der Benutzerumgebung vorschreiben, welche Zeichenkodierung verwendet werden soll. Wenn Python die Einstellungen nicht automatisch übernimmt,PYTHONIOENCODING
kann dies für Ihr Skript festgelegt werden. Sie sollten es nicht benötigen, es sei denn, die Ausgabe wird in eine Datei / Pipe umgeleitet.mach den Job, kann ihn aber nicht auf Python selbst einstellen ...
Was wir tun können, ist zu überprüfen, ob es nicht eingestellt ist, und den Benutzer anzuweisen, es vor dem Aufruf des Skripts festzulegen mit:
Update, um auf den Kommentar zu antworten: Das Problem besteht nur beim Weiterleiten an stdout. Ich habe in Fedora 25 Python 2.7.13 getestet
Katze b.py.
läuft ./b.py
läuft ./b.py | weniger
quelle
sys.stdout.encoding
wird automatisch basierend auf demLC_CTYPE
Gebietsschemawert festgelegt.Ich hatte letzte Woche ein ähnliches Problem . Es war einfach in meiner IDE (PyCharm) zu beheben.
Hier war mein Fix:
Ausgehend von der PyCharm-Menüleiste: Datei -> Einstellungen ... -> Editor -> Dateicodierungen, dann festlegen: "IDE-Codierung", "Projektcodierung" und "Standardcodierung für Eigenschaftendateien" ALL bis UTF-8 und sie arbeitet jetzt wie ein Zauber.
Hoffe das hilft!
quelle
Eine wohl bereinigte Version von Craig McQueens Antwort.
Verwendungszweck:
quelle
Ich könnte es mit einem Aufruf "automatisieren":
Ja, es ist möglich, hier eine Endlosschleife zu erhalten, wenn dieses "Setenv" fehlschlägt.
quelle
Ich dachte nur, ich würde hier etwas erwähnen, mit dem ich lange experimentieren musste, bevor ich endlich realisierte, was los war. Dies mag für alle hier so offensichtlich sein, dass sie sich nicht die Mühe gemacht haben, es zu erwähnen. Aber es hätte mir geholfen, wenn sie es getan hätten, also nach diesem Prinzip ...!
NB: Ich verwende Jython speziell, Version 2.7, daher gilt dies möglicherweise nicht für CPython ...
NB2: Die ersten beiden Zeilen meiner .py-Datei hier sind:
Der String-Konstruktionsmechanismus "%" (AKA "Interpolationsoperator") verursacht auch ZUSÄTZLICHE Probleme ... Wenn die Standardcodierung der "Umgebung" ASCII ist und Sie versuchen, so etwas zu tun
Sie werden keine Schwierigkeiten haben, in Eclipse zu laufen ... In einer Windows-CLI (DOS-Fenster) werden Sie feststellen, dass die Codierung Codepage 850 (mein Windows 7-Betriebssystem) oder etwas Ähnliches ist, das zumindest Zeichen mit europäischem Akzent verarbeiten kann werde arbeiten.
wird auch funktionieren.
Wenn Sie, OTOH, von der CLI aus auf eine Datei verweisen, lautet die Standardcodierung None. Dies ist standardmäßig ASCII (auf meinem Betriebssystem ohnehin), das keinen der oben genannten Ausdrucke verarbeiten kann ... (gefürchtete Codierung) Error).
Dann könnten Sie daran denken, Ihr Standard mithilfe von umzuleiten
und versuchen Sie, die CLI-Piping zu einer Datei auszuführen ... Sehr seltsamerweise funktioniert Druck A oben ... Aber Druck B oben löst den Codierungsfehler aus! Folgendes funktioniert jedoch einwandfrei:
Die Schlussfolgerung, zu der ich (vorläufig) gekommen bin, ist, dass, wenn eine Zeichenfolge, die als Unicode- Zeichenfolge mit dem Präfix "u" angegeben ist, an den% -Handhabungsmechanismus gesendet wird, anscheinend die Verwendung der Standardumgebungscodierung unabhängig davon verwendet wird ob Sie stdout auf Weiterleiten eingestellt haben!
Wie die Leute damit umgehen, ist eine Frage der Wahl. Ich würde einen Unicode-Experten begrüßen, der sagt, warum dies passiert, ob ich es irgendwie falsch verstanden habe, was die bevorzugte Lösung dafür ist, ob es auch für CPython gilt , ob es in Python 3 passiert usw. usw.
quelle
"fréd"
es sich um eine Byte-Sequenz und nicht um eine Unicode-Zeichenfolge handelt, sodass dercodecs.getwriter
Wrapper sie in Ruhe lässt. Sie brauchen eine Führungu
, oderfrom __future__ import unicode_literals
.Ich bin in einer älteren Anwendung auf dieses Problem gestoßen, und es war schwierig zu identifizieren, wo was gedruckt wurde. Ich habe mir bei diesem Hack geholfen:
Zusätzlich zu meinem Skript test.py:
Beachten Sie, dass dadurch ALLE Aufrufe zum Drucken geändert werden, um eine Codierung zu verwenden, sodass Ihre Konsole Folgendes druckt:
quelle
Unter Windows hatte ich dieses Problem sehr oft, wenn ich einen Python-Code in einem Editor (wie Sublime Text) ausführte, aber nicht, wenn ich ihn über die Befehlszeile ausführte.
Überprüfen Sie in diesem Fall die Parameter Ihres Editors. Im Fall von SublimeText wurde dies
Python.sublime-build
gelöst:quelle