it-swarm.com.de

Wie drucke ich UTF-8-codierten Text in Python <3?

Ich verwende ein aktuelles Linux-System, bei dem alle meine Ländereinstellungen UTF-8 sind:

LANG=de_DE.UTF-8
LANGUAGE=
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
...
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=

Jetzt möchte ich UTF-8-codierten Inhalt in die Konsole schreiben.

Im Moment verwendet Python UTF-8 für die FS Codierung, bleibt aber bei ASCII für die Standardcodierung :

>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.getfilesystemencoding()
'UTF-8'

Ich dachte, der beste (saubere) Weg, dies zu tun, war das Setzen der Umgebungsvariablen PYTHONIOENCODING. Aber es scheint, dass Python ignoriert es. Zumindest auf meinem System bekomme ich immer noch ascii als Standardkodierung, auch nach dem Setzen von envvar.

# tried this in ~/.bashrc and ~/.profile (also sourced them)
# and on the commandline before running python
export PYTHONIOENCODING=UTF-8

Wenn ich zu Beginn eines Skripts Folgendes mache, funktioniert es trotzdem:

>>> import sys
>>> reload(sys)  # to enable `setdefaultencoding` again
<module 'sys' (built-in)>
>>> sys.setdefaultencoding("UTF-8")
>>> sys.getdefaultencoding()
'UTF-8'

Aber dieser Ansatz scheint unsauber . Was ist also ein guter Weg, um dies zu erreichen?

Workaround

Anstatt die Standardcodierung zu ändern - was keine gute Idee ist (siehe die Antwort von Mesilliac) -, wickle ich sys.stdout mit einem StreamWriter wie folgt:

sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)

Siehe --- (this Gist für eine kleine Utility-Funktion, die damit umgeht.

47
Brutus

Wie drucke ich UTF-8-codierten Text in Python <3?

print u"some unicode text \N{EURO SIGN}"
print b"some utf-8 encoded bytestring \xe2\x82\xac".decode('utf-8')

wenn Sie eine Unicode-Zeichenfolge haben, drucken Sie diese direkt aus. Wenn Sie einen Bytestring haben, konvertieren Sie ihn zuerst in Unicode.

Ihre Gebietsschemaeinstellungen (LANG, LC_CTYPE) Geben ein UTF-8-Gebietsschema an. Daher können Sie (theoretisch) einen UTF-8-Bytestring direkt drucken und dieser sollte in Ihrem Terminal korrekt angezeigt werden (sofern zutreffend) Terminaleinstellungen stimmen mit den Gebietsschemaeinstellungen überein und sollten lauten. Sie sollten dies jedoch vermeiden: Codieren Sie die Zeichencodierung Ihrer Umgebung in Ihrem Skript nicht hart ; druckt statt direkt Unicode.

Ihre Frage enthält viele falsche Annahmen.

Sie müssen PYTHONIOENCODING nicht mit Ihren Gebietsschemaeinstellungen festlegen, um Unicode auf dem Terminal zu drucken. Das UTF-8-Gebietsschema unterstützt alle Unicode-Zeichen, d. h. es funktioniert wie es ist.

Sie benötigen die Problemumgehung sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout) nicht. Es kann zu Fehlern kommen, wenn ein Code (den Sie nicht kontrollieren) Bytes drucken muss und/oder während Drucken von Unicode in der Windows-Konsole (falsche Codepage, nicht decodierbare Zeichen können nicht gedruckt werden . Die korrekten Gebietsschemaeinstellungen und/oder PYTHONIOENCODING envvar sind ausreichend. Auch wenn Sie sys.stdout Ersetzen müssen, dann verwenden Sie io.TextIOWrapper() anstelle von codecs module wie win-unicode-console Package tut.

sys.getdefaultencoding() hat keine Beziehung zu Ihren Ländereinstellungen und zu PYTHONIOENCODING. Ihre Annahme, dass die Einstellung PYTHONIOENCODINGsys.getdefaultencoding() ändern sollte, ist falsch. Sie sollten stattdessen sys.stdout.encoding Aktivieren.

sys.getdefaultencoding() wird nicht verwendet, wenn Sie über die Konsole drucken. Es kann als Fallback für Python 2 verwendet werden, wenn stdout in eine Datei/Pipe umgeleitet wird, sofern nicht PYTHOHIOENCODING gesetzt ist:

$ python2 -c'import sys; print(sys.stdout.encoding)'
UTF-8
$ python2 -c'import sys; print(sys.stdout.encoding)' | cat
None
$ PYTHONIOENCODING=utf8 python2 -c'import sys; print(sys.stdout.encoding)' | cat
utf8

Rufen Sie nicht sys.setdefaultencoding("UTF-8") auf; Es kann Ihre Daten unbemerkt beschädigen und/oder Module von Drittanbietern beschädigen, die dies nicht erwarten. Denken Sie daran, dass sys.getdefaultencoding() verwendet wird, um Bytestrings (str) implizit in/von unicode in Python 2 zu konvertieren zB "a" + u"b" Siehe auch das Zitat in der Antwort von @ mesilliac .

8
jfs

Es scheint, dass dies nicht empfohlen wird.

Fedora schlug vor nter Verwendung des Systemgebietsschemas als Standard , aber anscheinend bricht dies andere Dinge.

Hier ist ein Zitat aus der Mailing-List-Diskussion :

 Die einzigen in Python unterstützten Standardcodierungen sind: 
 
 Python 2.x: ASCII 
 Python 3.x: UTF-8 
 
 Wenn Sie diese ändern, sind Sie auf sich allein gestellt und seltsame Dinge werden 
 Beginnen Die Standardcodierung wirkt sich nicht nur auf 
 die Übersetzung zwischen Python und der Außenwelt aus, sondern auch auf 
 alle internen Konvertierungen zwischen 8-Bit-Zeichenfolgen und Unicode . 
 
 Hacks wie das, was im pango-Modul passiert (Setzen der 
 Standardcodierung auf 'utf-8', indem das Site-Modul in der Reihenfolge 
 Neu geladen wird, um die sys.setdefaultencoding () API back) ist einfach 
 völlig falsch und führt zu schwerwiegenden Problemen, da Unicode-Objekte 
 ihre standardmäßig codierte Darstellung zwischenspeichern. 
 
 Bitte nicht Aktivieren Sie die Verwendung einer auf dem Gebietsschema basierenden Standardcodierung. 
 
 Wenn Sie nur die Codierungen von 
 stdout und stdin korrekt für Pipes einrichten möchten, sollten Sie 
 inst Sie müssen das .encoding-Attribut dieser (nur) ändern. 
 
 - 
 Marc-Andre Lemburg 
 eGenix.com 
28
mesilliac

So mache ich es:

#!/usr/bin/python2.7 -S

import sys
sys.setdefaultencoding("utf-8")
import site

Beachten Sie das -S in der Bangline. Das bedeutet, dass Python das site -Modul nicht automatisch importieren soll. Das site -Modul legt die Standardcodierung fest und entfernt die Methode, so dass dies nicht möglich ist wieder einstellen. Aber wird ehren, was bereits eingestellt ist.

23
Keith

Wenn das Programm nicht die entsprechenden Zeichen auf dem Bildschirm anzeigt, d. H. Ein ungültiges Symbol, führen Sie das Programm mit der folgenden Befehlszeile aus:

PYTHONIOENCODING=utf8 python3 yourprogram.py

Oder das Folgende, wenn Ihr Programm ein global installiertes Modul ist:

PYTHONIOENCODING=utf8 yourprogram

Auf einigen Plattformen als Cygwin (mintty.exe terminal) mit Anaconda Python (oder Python 3), starte einfach export PYTHONIOENCODING=utf8 und später funktioniert das Programm nicht, und Sie müssen es jedes Mal tun, wenn PYTHONIOENCODING=utf8 yourprogram, um das Programm korrekt auszuführen.

Unter Linux können Sie im Fall von Sudo versuchen, -E Argument zum Exportieren der Benutzervariablen in den Sudo-Prozess:

export PYTHONIOENCODING=utf8
Sudo -E python yourprogram.py

Wenn Sie dies versuchen und es nicht funktioniert hat, müssen Sie eine Sudo-Shell eingeben:

Sudo /bin/bash
PYTHONIOENCODING=utf8 yourprogram

Verbunden:

  1. So drucken Sie UTF-8-codierten Text in Python <3? auf die Konsole
  2. Ändern der Standardcodierung von Python?
  3. TF-8 über cp1252 (Python3) erzwingen
  4. Festgelegter Python Pfad für Anaconda in Cygwin
  5. https://superuser.com/questions/1374339/what-does-the-e-in-Sudo-e-do
  6. Warum gibt bash -c 'var = 5 printf "$ var"' nicht 5 aus?
  7. https://unix.stackexchange.com/questions/296838/whats-the-difference-inter-eval-and-exec
3
user