PEP 263 – Definieren von Python-Quellcode-Kodierungen
- Autor:
- Marc-André Lemburg <mal at lemburg.com>, Martin von Löwis <martin at v.loewis.de>
- Status:
- Final
- Typ:
- Standards Track
- Erstellt:
- 06-Jun-2001
- Python-Version:
- 2.3
- Post-History:
Zusammenfassung
Dieser PEP schlägt die Einführung einer Syntax vor, um die Kodierung einer Python-Quelldatei zu deklarieren. Die Kodierungsinformationen werden dann vom Python-Parser verwendet, um die Datei mit der gegebenen Kodierung zu interpretieren. Dies verbessert insbesondere die Interpretation von Unicode-Literalen im Quellcode und ermöglicht es, Unicode-Literale z. B. direkt mit UTF-8 in einem Unicode-fähigen Editor zu schreiben.
Problem
In Python 2.1 können Unicode-Literale nur mit der Latin-1-basierten Kodierung „unicode-escape“ geschrieben werden. Dies macht die Programmierumgebung für Python-Benutzer, die in Nicht-Latin-1-Lokalen leben und arbeiten, wie z. B. in vielen asiatischen Ländern, eher unfreundlich. Programmierer können ihre 8-Bit-Zeichenketten mit ihrer bevorzugten Kodierung schreiben, sind aber für Unicode-Literale an die „unicode-escape“-Kodierung gebunden.
Vorgeschlagene Lösung
Ich schlage vor, die Kodierung von Python-Quellcode sowohl sichtbar als auch änderbar pro Quelldatei zu machen, indem ein spezieller Kommentar am Anfang der Datei zur Deklaration der Kodierung verwendet wird.
Damit Python diese Kodierungsdeklaration erkennt, sind einige konzeptionelle Änderungen im Umgang mit Python-Quellcodedaten erforderlich.
Die Kodierung definieren
Python verwendet standardmäßig ASCII als Standardkodierung, wenn keine anderen Kodierungshinweise gegeben werden.
Um eine Quellcode-Kodierung zu definieren, muss ein magischer Kommentar in die Quelldateien entweder als erste oder zweite Zeile in der Datei platziert werden, wie z. B.
# coding=<encoding name>
oder (unter Verwendung von Formaten, die von gängigen Editoren erkannt werden)
#!/usr/bin/python
# -*- coding: <encoding name> -*-
oder
#!/usr/bin/python
# vim: set fileencoding=<encoding name> :
Genauer gesagt, die erste oder zweite Zeile muss dem folgenden regulären Ausdruck entsprechen
^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)
Die erste Gruppe dieses Ausdrucks wird dann als Kodierungsname interpretiert. Wenn die Kodierung Python unbekannt ist, wird während der Kompilierung ein Fehler ausgelöst. Auf der Zeile, die die Kodierungsdeklaration enthält, darf keine Python-Anweisung stehen. Wenn die erste Zeile übereinstimmt, wird die zweite Zeile ignoriert.
Um Plattformen wie Windows zu unterstützen, die Unicode BOM-Marken am Anfang von Unicode-Dateien hinzufügen, wird die UTF-8-Signatur \xef\xbb\xbf ebenfalls als „utf-8“-Kodierung interpretiert (auch wenn kein magischer Kodierungskommentar gegeben ist).
Wenn eine Quelldatei sowohl die UTF-8 BOM-Marken-Signatur als auch einen magischen Kodierungskommentar verwendet, ist die einzig zulässige Kodierung für den Kommentar „utf-8“. Jede andere Kodierung führt zu einem Fehler.
Beispiele
Hier sind einige Beispiele, um die verschiedenen Stile zur Definition der Quellcode-Kodierung am Anfang einer Python-Quelldatei zu verdeutlichen
- Mit Interpreter-Binary und unter Verwendung des Emacs-Stil-Dateikodierungs-Kommentars
#!/usr/bin/python # -*- coding: latin-1 -*- import os, sys ... #!/usr/bin/python # -*- coding: iso-8859-15 -*- import os, sys ... #!/usr/bin/python # -*- coding: ascii -*- import os, sys ...
- Ohne Interpreter-Zeile, unter Verwendung von reinem Text
# This Python file uses the following encoding: utf-8 import os, sys ...
- Texteditoren können unterschiedliche Möglichkeiten haben, die Kodierung der Datei zu definieren, z. B.
#!/usr/local/bin/python # coding: latin-1 import os, sys ...
- Ohne Kodierungskommentar nimmt der Python-Parser ASCII-Text an
#!/usr/local/bin/python import os, sys ...
- Kodierungs-Kommentare, die nicht funktionieren
- Fehlender „coding:“-Präfix
#!/usr/local/bin/python # latin-1 import os, sys ...
- Kodierungs-Kommentar nicht in Zeile 1 oder 2
#!/usr/local/bin/python # # -*- coding: latin-1 -*- import os, sys ...
- Nicht unterstützte Kodierung
#!/usr/local/bin/python # -*- coding: utf-42 -*- import os, sys ...
- Fehlender „coding:“-Präfix
Konzepte
Der PEP basiert auf den folgenden Konzepten, die implementiert werden müssten, um die Verwendung eines solchen magischen Kommentars zu ermöglichen
- Die vollständige Python-Quelldatei sollte eine einzige Kodierung verwenden. Das Einbetten von unterschiedlich kodierten Daten ist nicht gestattet und führt zu einem Dekodierungsfehler während der Kompilierung des Python-Quellcodes.
Jede Kodierung, die die Verarbeitung der ersten beiden Zeilen auf die oben angegebene Weise ermöglicht, ist als Quellcode-Kodierung zulässig, einschließlich ASCII-kompatibler Kodierungen sowie bestimmter Multibyte-Kodierungen wie Shift_JIS. Sie schließt Kodierungen aus, die für alle Zeichen zwei oder mehr Bytes verwenden, wie z. B. UTF-16. Der Grund dafür ist, den Algorithmus zur Kodierungserkennung im Tokenizer einfach zu halten.
- Die Behandlung von Escape-Sequenzen sollte weiterhin wie bisher funktionieren, jedoch mit allen möglichen Quellcode-Kodierungen. Das heißt, Standard-Zeichenkettenliterale (sowohl 8-Bit als auch Unicode) unterliegen der Expansion von Escape-Sequenzen, während Raw-Zeichenkettenliterale nur eine sehr kleine Teilmenge von Escape-Sequenzen erweitern.
- Pythons Tokenizer/Compiler-Kombination muss wie folgt aktualisiert werden:
- die Datei lesen
- sie in Unicode dekodieren, wobei eine feste Kodierung pro Datei angenommen wird
- sie in eine UTF-8-Byte-Zeichenkette konvertieren
- den UTF-8-Inhalt tokenisieren
- sie kompilieren, wobei Unicode-Objekte aus den gegebenen Unicode-Daten erstellt werden und Zeichenkettenobjekte aus den Unicode-Literal-Daten, indem zunächst die UTF-8-Daten mithilfe der gegebenen Dateikodierung zurück in 8-Bit-Zeichenketten-Daten kodiert werden
Beachten Sie, dass Python-Bezeichner auf die ASCII-Teilmenge der Kodierung beschränkt sind und nach Schritt 4 keiner weiteren Konvertierung bedürfen.
Implementierung
Um die Abwärtskompatibilität mit vorhandenem Code zu gewährleisten, der derzeit Nicht-ASCII in Zeichenkettenliteralen ohne Deklaration einer Kodierung verwendet, wird die Implementierung in zwei Phasen eingeführt
- Nicht-ASCII in Zeichenkettenliteralen und Kommentaren zulassen, indem intern eine fehlende Kodierungsdeklaration als Deklaration von „iso-8859-1“ behandelt wird. Dies führt dazu, dass willkürliche Byte-Zeichenketten korrekt zwischen Schritt 2 und Schritt 5 der Verarbeitung hin- und hergehen und Kompatibilität mit Python 2.2 für Unicode-Literale bieten, die Nicht-ASCII-Bytes enthalten.
Eine Warnung wird ausgegeben, wenn Nicht-ASCII-Bytes im Eingabe gefunden werden, einmal pro falsch kodierter Eingabedatei.
- Die Warnung entfernen und die Standardkodierung auf „ascii“ ändern.
Die eingebaute compile() API wird erweitert, um Unicode als Eingabe zu akzeptieren. 8-Bit-Zeichenketten-Eingaben unterliegen dem Standardverfahren zur Kodierungserkennung, wie oben beschrieben.
Wenn eine Unicode-Zeichenkette mit einer Codierungsdeklaration an compile() übergeben wird, wird ein SyntaxError ausgelöst.
SUZUKI Hisao arbeitet an einem Patch; siehe [2] für Details. Ein Patch, der nur Phase 1 implementiert, ist unter [1] verfügbar.
Phasen
Die Implementierung der Schritte 1 und 2 wurde in 2.3 abgeschlossen, mit Ausnahme der Änderung der Standardkodierung auf „ascii“.
Die Standardkodierung wurde in Version 2.5 auf „ascii“ gesetzt.
Umfang
Dieser PEP zielt darauf ab, einen Upgrade-Pfad von der derzeitigen (mehr oder weniger) undefinierten Situation der Quellcode-Kodierung zu einer robusteren und portableren Definition zu bieten.
Referenzen
Historie
- 1.10 und höher: siehe CVS-Historie
- 1.8: Punkt zum Coding-RE hinzugefügt.
- 1.7: Warnungen zur Phase-1-Implementierung hinzugefügt. Die Latin-1-Standardkodierung wurde durch die Standardkodierung des Interpreters ersetzt. Optimierungen an
compile()vorgenommen. - 1.4 - 1.6: Kleinere Anpassungen
- 1.3: Kommentare von Martin v. Loewis eingearbeitet: UTF-8 BOM-Marken-Erkennung, Emacs-Stil magischer Kommentar, zweistufiger Ansatz zur Implementierung
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0263.rst
Zuletzt geändert: 2025-02-01 08:55:40 GMT