Ich habe einige Py-Skripte gesehen, die dies oben im Skript verwenden. In welchen Fällen sollte man es benutzen?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Ich habe einige Py-Skripte gesehen, die dies oben im Skript verwenden. In welchen Fällen sollte man es benutzen?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Antworten:
Gemäß Dokumentation: Auf diese Weise können Sie vom Standard-ASCII zu anderen Codierungen wie UTF-8 wechseln, die die Python-Laufzeit immer dann verwendet, wenn ein Zeichenfolgenpuffer in Unicode dekodiert werden muss.
Diese Funktion ist nur beim Start von Python verfügbar, wenn Python die Umgebung scannt. Es muss in einem systemweiten Modul aufgerufen werden. sitecustomize.py
Nachdem dieses Modul ausgewertet wurde, wird die setdefaultencoding()
Funktion aus dem sys
Modul entfernt.
Die einzige Möglichkeit, es tatsächlich zu verwenden, ist ein Reload-Hack, der das Attribut zurückbringt.
Auch von der Verwendung von sys.setdefaultencoding()
wurde immer abgeraten , und es ist in py3k ein No-Op geworden. Die Codierung von py3k ist fest mit "utf-8" verbunden, und das Ändern dieser Codierung führt zu einem Fehler.
Ich schlage einige Hinweise zum Lesen vor:
sys.stdout
eine None
Codierung, z. B. beim Umleiten der Ausgabe eines Python-Programms).
sys.setdefaultencoding()
wurde immer entmutigt"
UTF-8
. LC_ALL=en_US.UTF-8 python3 -c 'import sys; print(sys.stdout.encoding)'
gibt UTF-8
aber LC_ALL=C python3 -c 'import sys; print(sys.stdout.encoding)'
gibt ANSI_X3.4-1968
(oder vielleicht etwas anderes)
Die Antwort ist NIE ! (es sei denn, Sie wissen wirklich, was Sie tun)
Das 9/10-fache der Lösung kann mit einem angemessenen Verständnis der Codierung / Decodierung gelöst werden.
1/10 Personen haben ein falsch definiertes Gebietsschema oder eine falsch definierte Umgebung und müssen Folgendes festlegen:
PYTHONIOENCODING="UTF-8"
in ihrer Umgebung, um Konsolendruckprobleme zu beheben.
(durchgestrichen, um eine Wiederverwendung zu vermeiden) Ändert die Standardcodierung / -decodierung, die verwendet wird, wenn Python 2.x einen Unicode () in einen str () konvertieren muss (und umgekehrt) und die Codierung nicht angegeben wird. Dh:sys.setdefaultencoding("utf-8")
str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC")
In Python 2.x ist die Standardcodierung auf ASCII festgelegt, und die obigen Beispiele schlagen fehl mit:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
(Meine Konsole ist als UTF-8 konfiguriert "€" = '\xe2\x82\xac'
, daher Ausnahme auf \xe2
)
oder
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
wird zulassen, dass diese für mich funktionieren , aber nicht unbedingt für Leute, die UTF-8 nicht verwenden. Die Standardeinstellung von ASCII stellt sicher, dass Annahmen zur Codierung nicht in Code eingebettet werdensys.setdefaultencoding("utf-8")
hat auch den Nebeneffekt sys.setdefaultencoding("utf-8")
sys.stdout.encoding
, dass es beim Drucken von Zeichen auf die Konsole angezeigt wird. Python verwendet das Gebietsschema des Benutzers (Linux / OS X / Un * x) oder die Codepage (Windows), um dies festzulegen. Gelegentlich ist das Gebietsschema eines Benutzers fehlerhaft und es muss nur PYTHONIOENCODING
die Konsolencodierung korrigiert werden .
Beispiel:
$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()
$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€
Die Leute entwickeln seit 16 Jahren gegen Python 2.x mit dem Verständnis, dass die Standardcodierung ASCII ist. UnicodeError
Es wurden Ausnahmebehandlungsmethoden geschrieben, um die Konvertierung von Zeichenfolgen in Unicode für Zeichenfolgen zu verarbeiten, die Nicht-ASCII enthalten.
Von https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/
def welcome_message(byte_string):
try:
return u"%s runs your business" % byte_string
except UnicodeError:
return u"%s runs your business" % unicode(byte_string,
encoding=detect_encoding(byte_string))
print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))
Vor dem Festlegen der Standardcodierung konnte dieser Code das „Å“ in der ASCII-Codierung nicht dekodieren und gab dann den Ausnahmehandler ein, um die Codierung zu erraten und sie ordnungsgemäß in Unicode umzuwandeln. Drucken: Angstrom (Å®) führt Ihr Unternehmen. Sobald Sie die Standardcodierung auf utf-8 gesetzt haben, stellt der Code fest, dass der byte_string als utf-8 interpretiert werden kann. Dadurch werden die Daten entstellt und stattdessen zurückgegeben: Angstrom (Ů) führt Ihr Unternehmen aus.
Das Ändern einer Konstanten hat dramatische Auswirkungen auf die Module, von denen Sie abhängig sind. Es ist besser, nur die Daten zu korrigieren, die in Ihren Code ein- und ausgehen.
Während die Einstellung der Standardcodierung auf UTF-8 im folgenden Beispiel nicht die Hauptursache ist, zeigt sie, wie Probleme maskiert werden und wie der Code bei Änderungen der Eingabecodierung auf nicht offensichtliche Weise unterbrochen wird: UnicodeDecodeError: 'utf8' Codec kann Byte 0x80 an Position 3131 nicht dekodieren: ungültiges Startbyte
sys.setdefaultencoding("utf-8")
, aber es ist gut, den Code eher wie Python 3 zu verhalten. Es ist jetzt 2017. Selbst als Sie die Antwort im Jahr 2015 geschrieben haben, war es meiner Meinung nach schon besser, vorwärts als rückwärts zu schauen. Es war tatsächlich die einfachste Lösung für mich, als ich feststellte, dass sich mein Code in Python 2 unterschiedlich verhält, je nachdem, ob die Ausgabe umgeleitet wird (sehr unangenehmes Problem für Python 2). Unnötig zu # coding: utf-8
erwähnen , dass ich dies bereits getan habe und keine Problemumgehungen für Python 3 benötige (ich muss die setdefaultencoding
Überprüfung der verwendeten Version tatsächlich maskieren ).
sys.setdefaultencoding("utf-8")
macht Ihren Py 2.x-Code jedoch nicht mit Python 3 kompatibel. Es werden auch keine externen Module repariert, bei denen davon ausgegangen wird, dass die Standardcodierung ASCII ist. Die Kompatibilität Ihres Codes mit Python 3 ist sehr einfach und erfordert diesen bösen Hack nicht. Zum Beispiel, warum dies sehr reale Probleme verursacht, siehe meine Erfahrung mit Amazon, die mit dieser Annahme herumspielt
PYTHONIOENCODING="UTF-8"
half meine Python2.7 Django-1.11-Umgebung. Vielen Dank.
detect_encoding
.
detect_encoding
ist eine Methode, mit der die Codierung einer Zeichenfolge anhand von Sprachhinweisen erkannt werden kann.
#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u
chmod +x test.py
./test.py
moçambique
moçambique
./test.py > output.txt
Traceback (most recent call last):
File "./test.py", line 5, in <module>
print u
UnicodeEncodeError: 'ascii' codec can't encode character
u'\xe7' in position 2: ordinal not in range(128)
Bei Shell funktioniert das Senden an sdtout nicht, das ist also eine Problemumgehung, um an stdout zu schreiben.
Ich habe einen anderen Ansatz gewählt, der nicht ausgeführt wird, wenn sys.stdout.encoding nicht definiert ist oder mit anderen Worten, zuerst PYTHONIOENCODING = UTF-8 exportiert werden muss, um in stdout zu schreiben.
import sys
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)
Verwenden Sie also dasselbe Beispiel:
export PYTHONIOENCODING=UTF-8
./test.py > output.txt
wird funktionieren
Die erste Gefahr liegt in reload(sys)
.
Wenn Sie ein Modul neu laden, erhalten Sie in Ihrer Laufzeit tatsächlich zwei Kopien des Moduls. Das alte Modul ist wie alles andere ein Python-Objekt und bleibt am Leben, solange Verweise darauf vorhanden sind. Die Hälfte der Objekte zeigt also auf das alte Modul und die Hälfte auf das neue. Wenn Sie Änderungen vornehmen, werden Sie diese nie sehen, wenn ein zufälliges Objekt die Änderung nicht sieht:
(This is IPython shell)
In [1]: import sys
In [2]: sys.stdout
Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8>
In [3]: reload(sys)
<module 'sys' (built-in)>
In [4]: sys.stdout
Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0>
In [11]: import IPython.terminal
In [14]: IPython.terminal.interactiveshell.sys.stdout
Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
Nun sys.setdefaultencoding()
richtig
Alles, was davon betroffen ist, ist die implizite Konvertierungstr<->unicode
. utf-8
Ist nun die vernünftigste Codierung auf dem Planeten (abwärtskompatibel mit ASCII und allen), funktioniert die Konvertierung jetzt "nur", was könnte möglicherweise schief gehen?
Nun, alles. Und das ist die Gefahr.
UnicodeError
dass er für Nicht-ASCII-Eingaben ausgegeben wird, oder die Transcodierung mit einem Fehlerhandler, der jetzt ein unerwartetes Ergebnis erzeugt. Und da der gesamte Code mit der Standardeinstellung getestet wird, befinden Sie sich hier ausschließlich auf "nicht unterstütztem" Gebiet , und niemand gibt Ihnen Garantien für das Verhalten des Codes.