Über verschiedene Codierungen von Python 3

Es ist viel einfacher als Python 2, aber in einigen Umgebungen können in Python 3 unerwartete UnicodeErrors auftreten. Lassen Sie uns die Handhabung verschiedener Python-Codierungen ab Python 3.6 regeln.

Python-Codierung

filesystem encoding (sys.getfilesystemencoding())

Diese Codierung wird hauptsächlich für Dateipfade verwendet, aber auch für Befehlszeilenargumente. (Andernfalls haben Sie Probleme, den Dateipfad als Befehlszeilenargument zu übergeben.)

Da das Gebietsschema verwandt ist, wird es auch bei der Arbeit mit glibc usw. verwendet. Es mag ein Überbleibsel der Python 2-Ära sein, aber jetzt habe ich das Gefühl, dass die Bezeichnung Systemcodierung anstelle von Dateisystemcodierung die Realität darstellt.

preferred encoding (locale.getpreferredencoding())

Diese Codierung wird hauptsächlich für den Inhalt von Textdateien verwendet. Es wird verwendet, wenn eine Textdatei mit der Funktion "Öffnen" geöffnet wird.

Standard-Eingabe / Ausgabe-Codierung ( sys.stdout.encoding)

Die Standard-Eingabe- / Ausgabecodierung ist die Dateisystemcodierung für Terminals und die bevorzugte Codierung für andere, kann jedoch mit der Umgebungsvariablen "PYTHONIOENCODING" geändert werden.

default encoding (sys.getdefaultencoding())

Dies ist die Standardcodierung, die verwendet wird, wenn Sie beim Konvertieren zwischen einer Unicode-Zeichenfolge ( str) und einer Zeichenfolge von Bytes ( Bytes) keine explizite Codierung angeben. In Python 3 ist UTF-8 unabhängig von der Umgebung vollständig behoben.

>>> "Hallo".encode()
b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf'
>>> _.decode()
'Hallo'

Es war ASCII in der Python 2-Ära, und es gab eine implizite Typkonvertierung, so dass es tendenziell zu Problemen führte. (Es gab auch einen Hack, um utf-8 zu zwingen, eine App auszuführen, die nicht an Multibyte dachte.)

Python 3 führt keine implizite Typkonvertierung zwischen str und bytes durch, daher ist es nur ein Standardargument. Sie können die Existenz selbst vergessen.

Verhalten in verschiedenen Umgebungen

macOS, android

Da es auf Betriebssystemebene auf UTF-8 festgelegt ist, lautet die Dateisystemcodierung immer UTF-8.

Die bevorzugte Codierung ist immer UTF-8 für Android festgelegt und kann mit dem Gebietsschema für macOS geändert werden, aber ich denke, dass dies selten ein Problem ist. (Wenn das Gebietsschema festgelegt ist, entspricht es dem später beschriebenen Linux.)

Windows

Da Windows W-basierte APIs sowohl beim Öffnen von Dateien als auch beim Empfangen von Befehlszeilenargumenten verwendet, wird die Dateisystemcodierung selten verwendet.

Das Verhalten beim Umgang mit Dateipfaden als Bytezeichenfolgen war die aktuelle Codepage "cp932", da es sich bis Python 3.5 um einen Windows A-API-Aufruf handelte. Ab Python 3.6 hat sich dieses Verhalten geändert und UTF-8 => UTF-16-Konvertierung und W-basierte APIs werden verwendet, sodass die Dateisystemcodierung "utf-8" lautet. (Es gibt auch Umgebungsvariablen, die auf das Verhalten von Python 3.5 zurückgesetzt werden können.)

Die bevorzugte Codierung verwendet andererseits immer noch die Codepage. Es ist ein Vermächtnis, bis Microsoft die Standard-Textdatei für UTF-8 erstellt. Es tut mir Leid.

Linux, anderes Unix

Am enttäuschendsten ist das andere Unix. Dies hängt vom Gebietsschema ab ( LC_CTYPE). Wenn noch jemand "LANG = ja_JP.eucJP" sagt, ist sowohl die Dateisystemcodierung als auch die bevorzugte Codierung EUC-JP. Wenn Sie eine Textdatei in UTF-8 erstellen möchten, geben Sie die Codierung explizit mit der Funktion "Öffnen" für Umgebungen an, in denen das Gebietsschema nicht UTF-8 ist, auch wenn Sie Windows überhaupt nicht unterstützen möchten.

Die Abhängigkeit vom Gebietsschema ist besonders enttäuschend, da die Standardcodierung (C oder POSIX) (LC_CTYPE) für das Gebietsschema standardmäßig ASCII ist.

Einige Benutzer verwenden das Gebietsschema C oder POSIX, weil ihnen das Verhalten verschiedener Befehle wie Sortieren je nach Gebietsschema nicht gefällt. Integrierte oder Container-Images verfügen möglicherweise nicht über die Gebietsschemas en_US.utf8 oder ja_JP.utf8, um Gewicht zu sparen. Wenn Sie ssh von einem Mac ausführen (weil die Umgebungsvariable LANG gesendet wird), wird möglicherweise eine Fehlermeldung angezeigt und Sie greifen auf C zurück, wenn Sie versuchen, ja_JP.UTF-8 unter Linux zu verwenden, das nur en_US.UTF-8 enthält. Zu diesem Zeitpunkt befindet sich Python vollständig im ASCII-Modus.

$ export LC_ALL=C
$ echo 'print("Hallo\n")' > hello
$ ruby hello
Hallo
$ perl hello
Hallo
$ python3 hello
Traceback (most recent call last):
  File "hello", line 1, in <module>
    print("\u3053\u3093\u306b\u3061\u306f\n")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)

Wenn die Dateisystemcodierung ASCII bleiben kann, können Sie die Standardeingabe- / Ausgabecodierung mit PYTHONIOENCODING angeben, ohne das Gebietsschema festzulegen. Schreiben Sie es in .bashrc oder crontab.

$ PYTHONIOENCODING=utf-8 python3 hello
Hallo

(Anhang) Linux-Gebietsschemaeinstellungen für die Verwendung von UTF-8 mit Python

Das erste, woran Sie sich erinnern sollten, ist der Befehl locale, mit dem das aktuelle Gebietsschema angezeigt wird, und der Befehl locale -a, mit dem eine Liste der verfügbaren Gebietsschemas angezeigt wird.

$ locale
LANG=C.UTF-8
LANGUAGE=en_US:en
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_PAPER="C.UTF-8"
LC_NAME="C.UTF-8"
LC_ADDRESS="C.UTF-8"
LC_TELEPHONE="C.UTF-8"
LC_MEASUREMENT="C.UTF-8"
LC_IDENTIFICATION="C.UTF-8"
LC_ALL=

$ locale -a
C
C.UTF-8
POSIX
en_US.utf8

Ich denke, C.UTF-8 ist in modernem Linux enthalten. Eine UTF-8-Version des C-Gebietsschemas, die nichts Besonderes bewirkt. Es ist perfekt für Benutzer, die das Gebietsschema C verwenden möchten, aber UTF-8-Dateinamen verwenden möchten. Wenn es nicht vorhanden ist, sollten Sie es mit "sudo localedef -c -i POSIX -f UTF-8 C.UTF-8" erstellen können, wenn Sie über Root-Rechte verfügen.

Wenn ja_JP.UTF-8 oder en_US.UTF-8 vorhanden ist und Sie es verwenden möchten, legen Sie es in der Umgebungsvariablen LANG fest und überprüfen Sie es mit dem Befehl locale.

$ export LANG=en_US.utf8
$ locale
LANG=en_US.utf8
LANGUAGE=en_US:en
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=

Ich möchte das Gebietsschema C verwenden! Aber ich möchte UTF-8 verwenden! Aber ich kann C.UTF-8 nicht machen! Lassen Sie es uns in diesem Fall etwas genauer steuern. Von jedem LC_XXXXX ist derjenige, den Python zur Bestimmung der Codierung verwendet, "LC_CTYPE". Die Umgebungsvariable LANG setzt den gesamten LC_XXXX mit Ausnahme von LC_ALL und kann mit jedem LC_XXXX einzeln überschrieben werden. Wenn jedoch LC_ALL gesetzt ist, wird alles weiter überschrieben. Sie können LC_CTYPE also auf ein UTF-8-Gebietsschema setzen, während Sie LANG = C setzen.

$ export LANG=C
$ export LC_CTYPE=en_US.UTF-8
$ locale
LANG=C
LANGUAGE=en_US:en
LC_CTYPE=en_US.UTF-8
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=

$ locale charmap
UTF-8
$ python3 -c 'import sys; print(sys.getfilesystemencoding())'
utf-8

Recommended Posts

Über verschiedene Codierungen von Python 3
Verschiedene Verarbeitung von Python
Über die Funktionen von Python
Informationen zur Grundlagenliste der Python-Grundlagen
Über Python-Slices
Über die Einschlussnotation von Python
Informationen zum Erstellen einer GUI mit TKinter of Python
Über Python tqdm.
Über die Python-Ausbeute
Über Python, Klasse
Memorandum von Python-Anfängern
Zusammenfassung verschiedener for-Anweisungen in Python
Informationen zur Python-Vererbung
Python-Grundlagen ①
Grundlagen von Python ①
Über Python, range ()
# 3 [python3] Verschiedene Operatoren
Kopie von Python
Über Python Decorator
1. Mit Python 1-3 gelernte Statistiken. Berechnung verschiedener Statistiken (Statistiken)
Verschiedene Formatspezifikationen der str.format () -Methode von Python3
Informationen zur Python-Referenz
[Python] Verschiedene Kombinationen von Zeichenketten und Werten
Über Python-Dekorateure
Hinweis auf Probleme hinsichtlich der Koexistenz des Python 2/3-Systems
[Python] Kapitel 02-04 Grundlagen des Python-Programms (Informationen zu Kommentaren)
[Python] Über Multi-Prozess
Einführung von Python
[Python] Erstellen Sie eine Liste mit verschiedenen Zeichentypen
1. Mit Python 1-2 gelernte Statistiken. Berechnung verschiedener Statistiken (Numpy)
Schreiben Sie eine Notiz über die Python-Version von Python Virtualenv
Verschiedene Einstellungen des statischen Python-Blog-Generierungs-Tools 'Pelican'
[Hinweis] Über die Rolle des Unterstrichs "_" in Python
Über flache und tiefe Kopien von Python / Ruby
Über Python für Schleife
[Python] Operation der Aufzählung
Über Funktionsargumente (Python)
Über alles von numpy
Vereinheitlichung der Python-Umgebung
Kopie der Python-Einstellungen
Grundlagen der Python-Scraping-Grundlagen
Über die Zuweisung von numpy.ndarray
[Python] Verhalten von Argmax
[Python] Memo über Funktionen
Zusammenfassung über Python3 + OpenCV3
Verschiedene Python-Visualisierungstools
Verwendung von Python-Einheimischen ()
der Zen von Python
Über Python für ~ (Bereich)
Installieren von Python 3.3 rc1
[Python] Memo Über Fehler
Informationen zur Python-Entwicklungsumgebung
Python: Über Funktionsargumente
Python, über die Ausnahmebehandlung