Ich habe viele Probleme mit Python, bei denen ich meine Anwendungen von der Konsole aus ausführen kann. Aber in der Eclipse PyDev IDE ist die Standardzeichenkodierung auf UTF-8 eingestellt , und mir geht es gut.
Ich habe nach der Einstellung der Standardcodierung gesucht und die Leute sagen, dass Python die sys.setdefaultencoding
Funktion beim Start löscht und wir sie nicht verwenden können.
Was ist die beste Lösung dafür?
The best solution is to learn to use encode and decode correctly instead of using hacks.
Dies war mit python2 sicherlich möglich, und zwar auf Kosten der ständigen Erinnerung daran / der konsequenten Verwendung Ihrer eigenen Benutzeroberfläche. Meine Erfahrung zeigt, dass dies sehr problematisch wird, wenn Sie Code schreiben, mit dem Sie sowohl mit Python2 als auch mit Python3 arbeiten möchten.Antworten:
Hier ist eine einfachere Methode (Hack), mit der Sie die
setdefaultencoding()
Funktion zurückerhalten, aus der gelöscht wurdesys
:(Hinweis für Python 3.4+:
reload()
befindet sich in derimportlib
Bibliothek.)Dies ist jedoch keine sichere Sache : Dies ist offensichtlich ein Hack, da er
sys.setdefaultencoding()
absichtlich entfernt wird,sys
wenn Python gestartet wird. Durch erneutes Aktivieren und Ändern der Standardcodierung kann Code beschädigt werden, bei dem ASCII als Standard verwendet wird (dieser Code kann von Drittanbietern stammen, was das Beheben im Allgemeinen unmöglich oder gefährlich machen würde).quelle
LC_CTYPE
(oder in einer Anwendung prüfen, ob es richtig eingestellt ist, und mit einer aussagekräftigen Fehlermeldung abbrechen).LC_CTYPE=C python -c 'import locale; print( locale.getpreferredencoding())'
Wenn Sie diese Fehlermeldung erhalten, wenn Sie versuchen, die Ausgabe Ihres Skripts weiterzuleiten / umzuleiten
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
Exportieren Sie einfach PYTHONIOENCODING in die Konsole und führen Sie dann Ihren Code aus.
export PYTHONIOENCODING=utf8
quelle
LC_CTYPE
sinnvoll , anstatt auf etwas. Es macht auch alle anderen Programme glücklich.PYTHONIOENCODING=utf8
nicht die Standardeinstellung ist. Dies macht Skripte brechen nur, weilLC_ALL=C
Set LC_CTYPE to something sensible instead
Dies ist ein vernünftiger Vorschlag. Dies funktioniert nicht so gut, wenn Sie versuchen, Code zu verteilen, der nur auf dem System einer anderen Person funktioniert.C.utf8
Gebietsschema, um vernünftiger zu sein. C. glibc upstream arbeitet daran, es hinzuzufügen. Vielleicht sollten wir Python nicht beschuldigen, die Gebietsschemaeinstellungen zu respektieren \…?A) So steuern Sie die
sys.getdefaultencoding()
Ausgabe:ascii
Dann
und
utf-16-be
Sie könnten Ihre sitecustomize.py höher in Ihre setzen
PYTHONPATH
.Vielleicht
reload(sys).setdefaultencoding
möchten Sie es auch mit @EOL versuchenB) Um zu steuern
stdin.encoding
undstdout.encoding
Sie möchten einstellenPYTHONIOENCODING
:ascii ascii
Dann
utf-16-be utf-16-be
Endlich: Sie können A) oder B) oder beides verwenden!
quelle
from __future__ import unicode_literals
siehe DiskussionAb PyDev 3.4.1 wird die Standardkodierung nicht mehr geändert. Siehe dieses Ticket für Details.
Bei früheren Versionen besteht eine Lösung darin, sicherzustellen, dass PyDev nicht mit UTF-8 als Standardcodierung ausgeführt wird. Führen Sie unter Eclipse Dialogeinstellungen aus ("Konfigurationen ausführen", wenn ich mich richtig erinnere). Sie können die Standardcodierung auf der allgemeinen Registerkarte auswählen. Ändern Sie es in US-ASCII, wenn Sie diese Fehler "früh" haben möchten (mit anderen Worten: in Ihrer PyDev-Umgebung). Lesen Sie auch einen Original-Blogbeitrag zu dieser Problemumgehung .
quelle
In Bezug auf Python2 (und nur Python2) basieren einige der früheren Antworten auf der Verwendung des folgenden Hacks:
Es wird davon abgeraten, es zu verwenden (überprüfen Sie dies oder das )
In meinem Fall hat dies einen Nebeneffekt: Ich verwende Ipython-Notizbücher, und sobald ich den Code ausgeführt habe, funktioniert die Funktion "Drucken" nicht mehr. Ich denke, es würde eine Lösung dafür geben, aber ich denke trotzdem, dass die Verwendung des Hacks nicht die richtige Option sein sollte.
Nachdem ich viele Optionen ausprobiert hatte, verwendete die für mich funktionierende den gleichen Code in der
sitecustomize.py
, in der sich dieser Code befinden soll . Nach der Auswertung dieses Moduls wird die Funktion setdefaultencoding aus sys entfernt.Die Lösung besteht also darin,
/usr/lib/python2.7/sitecustomize.py
den Code anzuhängen :Wenn ich virtualenvwrapper verwende, ist die von mir bearbeitete Datei
~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py
.Und wenn ich es mit Python-Notizbüchern und Conda verwende, ist es das auch
~/anaconda2/lib/python2.7/sitecustomize.py
quelle
Es gibt einen aufschlussreichen Blog-Beitrag darüber.
Siehe https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/ .
Ich paraphrasiere seinen Inhalt unten.
In Python 2, das in Bezug auf die Codierung von Zeichenfolgen nicht so stark typisiert war, konnten Sie Operationen an unterschiedlich codierten Zeichenfolgen ausführen und erfolgreich sein. ZB würde das Folgende zurückkehren
True
.Dies würde für jede (normale, nicht vorfixierte) Zeichenfolge gelten, in
sys.getdefaultencoding()
der standardmäßig codiert wurde , fürascii
andere jedoch nicht.Die Standardcodierung sollte systemweit geändert werden
site.py
, jedoch nicht an einer anderen Stelle. Die Hacks (auch hier vorgestellt) zum Festlegen in Benutzermodulen waren genau das: Hacks, nicht die Lösung.Python 3 hat die Systemcodierung standardmäßig auf utf-8 geändert (wenn LC_CTYPE Unicode-fähig ist), aber das grundlegende Problem wurde mit der Anforderung gelöst, "Byte" -Strings explizit zu codieren, wenn sie mit Unicode-Strings verwendet werden.
quelle
Erstens: Das
reload(sys)
Festlegen einer zufälligen Standardcodierung nur in Bezug auf die Notwendigkeit eines Ausgabe-Terminal-Streams ist eine schlechte Praxis.reload
ändert häufig Dinge in sys, die je nach Umgebung eingerichtet wurden - z. B. sys.stdin / stdout-Streams, sys.excepthook usw.Lösen des Codierungsproblems auf stdout
Die beste Lösung, die ich kenne, um das Codierungsproblem zu lösen
print
, Unicode-Strings undstr
Beyond-ASCIIs (z. B. aus Literalen) auf sys.stdout zu lösen, ist: sich um ein sys.stdout (dateiähnliches Objekt) zu kümmern, das fähig ist und optional tolerant in Bezug auf die Bedürfnisse:Wenn
sys.stdout.encoding
esNone
aus irgendeinem Grund oder nicht vorhanden oder fälschlicherweise falsch oder "weniger" ist als das, wozu das Standardterminal oder der Standard-Stream wirklich in der Lage ist, versuchen Sie, ein korrektes.encoding
Attribut bereitzustellen . Zuletzt durch Ersetzensys.stdout & sys.stderr
durch ein übersetzendes dateiähnliches Objekt.Wenn das Terminal / der Stream immer noch nicht alle vorkommenden Unicode-Zeichen codieren kann und Sie diese nicht
print
nur aus diesem Grund unterbrechen möchten , können Sie ein Verhalten zum Codieren mit Ersetzen in das übersetzungsdateiähnliche Objekt einführen.Hier ein Beispiel:
Verwenden von einfachen String-Literalen jenseits von ASCII in Python 2/2 + 3-Code
Der einzige gute Grund, die globale Standardcodierung (nur auf UTF-8) zu ändern, betrifft meiner Meinung nach eine Entscheidung über den Quellcode der Anwendung - und nicht aufgrund von Problemen mit der Codierung von E / A-Streams: Zum Schreiben von String-Literalen über ASCII hinaus in Code, ohne dazu gezwungen zu werden um immer
u'string'
Style-Unicode-Escape zu verwenden. Dies kann ziemlich konsistent erfolgen (trotz des Artikels von anonbadger ), indem eine Python 2- oder Python 2 + 3-Quellcodebasis verwendet wird, die konsistente ASCII- oder UTF-8-Zeichenfolgenliterale konsistent verwendet - sofern diese Zeichenfolgen möglicherweise stumm geschaltet werden Unicode-Konvertierung und zwischen Modulen wechseln oder möglicherweise zu stdout wechseln. Dafür lieber "# encoding: utf-8
"oder ascii (keine Deklaration). Ändern oder Löschen von Bibliotheken, die sich immer noch auf sehr dumme Weise auf ASCII-Standardcodierungsfehler jenseits von chr # 127 stützen (was heute selten ist).Und tun Sie dies beim Start der Anwendung (und / oder über sitecustomize.py) zusätzlich zu dem
SmartStdout
oben beschriebenen Schema - ohne Folgendes zu verwendenreload(sys)
:Auf diese Weise funktionieren String-Literale und die meisten Operationen (mit Ausnahme der Zeicheniteration) komfortabel, ohne über die Unicode-Konvertierung nachzudenken, als gäbe es nur Python3. Datei-E / A benötigen natürlich immer besondere Sorgfalt bei der Codierung - wie in Python3.
Hinweis: Einfache Zeichenfolgen werden dann implizit von utf-8 in Unicode in
SmartStdout
konvertiert, bevor sie in den folgenden Ausgabestream konvertiert werden.quelle
Hier ist der Ansatz, mit dem ich Code erstellt habe, der sowohl mit python2 als auch mit python3 kompatibel war und immer eine utf8- Ausgabe erzeugte . Ich habe diese Antwort woanders gefunden, kann mich aber nicht an die Quelle erinnern.
Dieser Ansatz ersetzt
sys.stdout
durch etwas, das nicht ganz dateiähnlich ist (aber immer noch nur Dinge in der Standardbibliothek verwendet). Dies kann durchaus Probleme für Ihre zugrunde liegenden Bibliotheken verursachen. In dem einfachen Fall, in dem Sie eine gute Kontrolle darüber haben, wie sys.stdout out über Ihr Framework verwendet wird, kann dies ein vernünftiger Ansatz sein.quelle
Dies hat das Problem für mich behoben.
quelle
Dies ist ein schneller Hack für alle, die (1) auf einer Windows-Plattform (2) mit Python 2.7 und (3) verärgert sind, weil eine nette Software (dh nicht von Ihnen geschrieben, also nicht sofort ein Kandidat für das Codieren / Decodieren) ist Manöver) zeigen die "hübschen Unicode-Zeichen" in der IDLE-Umgebung nicht an (Pythonwin druckt Unicode-Fein), z. B. die sauberen Logiksymbole erster Ordnung, die Stephan Boyer in der Ausgabe seines pädagogischen Prüfers bei First Order Logic Prover verwendet .
Die Idee, ein sys-Reload zu erzwingen, gefiel mir nicht und ich konnte das System nicht dazu bringen, mit dem Festlegen von Umgebungsvariablen wie PYTHONIOENCODING zusammenzuarbeiten (versuchte es mit einer direkten Windows-Umgebungsvariablen und löschte diese auch in einer sitecustomize.py in Site-Paketen als Eins liner = 'utf-8').
Wenn Sie also bereit sind, Ihren Weg zum Erfolg zu hacken, wechseln Sie in Ihr IDLE-Verzeichnis. In der Regel: "C: \ Python27 \ Lib \ idlelib" Suchen Sie die Datei IOBinding.py. Erstellen Sie eine Kopie dieser Datei und speichern Sie sie an einem anderen Ort, damit Sie bei Bedarf zum ursprünglichen Verhalten zurückkehren können. Öffnen Sie die Datei in der Idlelib mit einem Editor (z. B. IDLE). Gehen Sie zu diesem Codebereich:
Mit anderen Worten, kommentieren Sie die ursprüngliche Codezeile nach dem ' Versuch ' aus, bei dem die Codierungsvariable gleich locale.getdefaultlocale wurde (da Sie dadurch cp1252 erhalten, was Sie nicht möchten), und erzwingen Sie sie stattdessen brutal auf 'utf-8' '(durch Hinzufügen der Zeile' encoding = 'utf-8 ' wie gezeigt).
Ich glaube, dies wirkt sich nur auf die IDLE-Anzeige auf stdout aus und nicht auf die Codierung, die für Dateinamen usw. verwendet wird (die zuvor in der Dateisystemcodierung erhalten wurde). Wenn Sie ein Problem mit einem anderen Code haben, den Sie später in IDLE ausführen, ersetzen Sie einfach die Datei IOBinding.py durch die ursprüngliche unveränderte Datei.
quelle
Sie können die Codierung Ihres gesamten Betriebssystems ändern. Unter Ubuntu können Sie dies mit tun
quelle