PEP 261 – Unterstützung für „breite“ Unicode-Zeichen
- Autor:
- Paul Prescod <paul at prescod.net>
- Status:
- Final
- Typ:
- Standards Track
- Erstellt:
- 27. Jun 2001
- Python-Version:
- 2.2
- Post-History:
- 27. Jun 2001
Zusammenfassung
Python 2.1 Unicode-Zeichen können nur Ordnungszahlen bis 2**16 - 1 haben. Dieser Bereich entspricht einem Bereich in Unicode, der als Basic Multilingual Plane (BMP) bekannt ist. Es gibt jetzt Zeichen in Unicode, die auf anderen „Ebenen“ liegen. Das größte adressierbare Zeichen in Unicode hat die Ordnungszahl 17 * 2**16 - 1 (0x10ffff). Zur besseren Lesbarkeit werden wir dies TOPCHAR nennen und Zeichen in diesem Bereich „breite Zeichen“ nennen.
Glossar
- Zeichen
- Alleine verwendet, bedeutet es die adressierbaren Einheiten eines Python-Unicode-Strings.
- Codepunkt
- Ein Codepunkt ist eine Ganzzahl zwischen 0 und TOPCHAR. Wenn Sie sich Unicode als eine Zuordnung von Ganzzahlen zu Zeichen vorstellen, ist jede Ganzzahl ein Codepunkt. Aber auch die Ganzzahlen zwischen 0 und TOPCHAR, die keinen Zeichen zugeordnet sind, sind Codepunkte. Einige werden eines Tages für Zeichen verwendet werden. Einige werden garantiert niemals für Zeichen verwendet werden.
- Codec
- Eine Sammlung von Funktionen zur Übersetzung zwischen physischen Kodierungen (z. B. auf der Festplatte oder aus dem Netzwerk kommend) und logischen Python-Objekten.
- Kodierung
- Mechanismus zur Darstellung abstrakter Zeichen in Form von physischen Bits und Bytes. Kodierungen ermöglichen es uns, Unicode-Zeichen auf der Festplatte zu speichern und sie über Netzwerke zu übertragen, auf eine Weise, die mit anderer Unicode-Software kompatibel ist.
- Surrogat-Paar
- Zwei physische Zeichen, die ein einzelnes logisches Zeichen darstellen. Teil einer Konvention zur Darstellung von 32-Bit-Codepunkten in Form von zwei 16-Bit-Codepunkten.
- Unicode-String
- Ein Python-Typ, der eine Sequenz von Codepunkten mit „String-Semantik“ darstellt (z. B. Groß-/Kleinschreibungsumwandlung, Kompatibilität mit regulären Ausdrücken usw.). Konstruiert mit der Funktion
unicode().
Vorgeschlagene Lösung
Eine Lösung wäre, lediglich die maximale Ordnungszahl auf einen größeren Wert zu erhöhen. Leider besteht die einzige direkte Implementierung dieser Idee darin, 4 Bytes pro Zeichen zu verwenden. Dies hat zur Folge, dass die meisten Unicode-Strings doppelt so groß werden. Um diese Kosten nicht jedem Benutzer aufzuerlegen, erlaubt Python 2.2 die 4-Byte-Implementierung als Build-Option. Benutzer können wählen, ob sie breite Zeichen benötigen oder Speicherplatz sparen möchten.
Die 4-Byte-Option wird als „breites Py_UNICODE“ bezeichnet. Die 2-Byte-Option wird als „schmales Py_UNICODE“ bezeichnet.
Die meisten Dinge werden sich in der breiten und schmalen Welt identisch verhalten.
unichr(i)für 0 <= i <2**16(0x10000) gibt immer einen String der Länge eins zurück.unichr(i)für2**16<= i <= TOPCHAR gibt auf breiten Python-Builds einen String der Länge eins zurück. Auf schmalen Builds wirdValueErrorausgelöst.PROBLEM
Python erlaubt derzeit\U-Literale, die nicht als einzelnes Python-Zeichen dargestellt werden können. Es erzeugt zwei Python-Zeichen, die als „Surrogat-Paar“ bezeichnet werden. Sollte dies bei zukünftigen schmalen Python-Builds verboten werden?Dafür
Python erlaubt bereits die Erstellung eines Surrogat-Paares für eine lange Unicode-Literal-Zeichen-Escape-Sequenz. Dies ist im Grunde als einfache Möglichkeit konzipiert, „breite Zeichen“ auch in einem schmalen Python-Build zu erstellen. Es ist auch einigermaßen logisch, da die Syntax für Unicode-Literale im Grunde eine Kurzform zur Aufrufung des Unicode-Escape-Codecs ist.Dagegen
Surrogate könnten auf diese Weise leicht erstellt werden, aber der Benutzer muss immer noch vorsichtig beim Slicing, Indexieren, Drucken usw. sein. Daher haben einige vorgeschlagen, dass Unicode-Literale keine Surrogate unterstützen sollten.PROBLEM
Sollte Python die Erstellung von Zeichen erlauben, die keinen Unicode-Codepunkten entsprechen? Nicht zugewiesene Unicode-Codepunkte sollten offensichtlich legal sein (da sie jederzeit zugewiesen werden könnten). Aber Codepunkte über TOPCHAR hinaus werden garantiert niemals von Unicode verwendet. Sollten wir ihnen trotzdem Zugriff gewähren?Dafür
Wenn ein Python-Benutzer glaubt, dass er weiß, was er tut, warum sollten wir versuchen, ihn daran zu hindern, die Unicode-Spezifikation zu verletzen? Immerhin hindern wir 8-Bit-Strings nicht daran, Nicht-ASCII-Zeichen zu enthalten.Dagegen
Codecs und anderer Unicode-verbrauchender Code muss vorsichtig mit diesen Zeichen sein, die von der Unicode-Spezifikation verboten sind.ord()ist immer die Umkehrfunktion vonunichr()- Es gibt im sys-Modul einen Ganzzahlwert, der die größte Ordnungszahl für ein Zeichen in einem Unicode-String im aktuellen Interpreter beschreibt.
sys.maxunicodeist2**16-1(0xffff) auf schmalen Python-Builds und TOPCHAR auf breiten Builds.PROBLEM
Sollte es separate Konstanten für den Zugriff auf TOPCHAR und die tatsächliche Obergrenze für die Domäne vonunichrgeben (falls sie sich unterscheiden)? Es gab auch den Vorschlag fürsys.unicodewidth, das die Werte'wide'und'narrow'annehmen kann. - Jedes Python-Unicode-Zeichen repräsentiert genau einen Unicode-Codepunkt (d. h. Python-Unicode-Zeichen = Abstraktes Unicode-Zeichen).
- Codecs werden aufgerüstet, um „breite Zeichen“ zu unterstützen (direkt in UCS-4 dargestellt und als variable Längen-Sequenzen in UTF-8 und UTF-16). Dies ist der Hauptteil der noch zu erledigenden Implementierung.
- Es gibt eine Konvention in der Unicode-Welt, einen 32-Bit-Codepunkt in Form von zwei 16-Bit-Codepunkten zu kodieren. Diese werden als „Surrogat-Paare“ bezeichnet. Pythons Codecs werden diese Konvention übernehmen und 32-Bit-Codepunkte als Surrogat-Paare auf schmalen Python-Builds kodieren.
PROBLEM
Sollte es eine Möglichkeit geben, Codecs anzuweisen, keine Surrogat-Zeichen zu generieren und stattdessen breite Zeichen als Fehler zu behandeln?Dafür
Ich möchte vielleicht Code schreiben, der nur mit festen Zeichenbreiten funktioniert und sich nicht um Surrogate kümmern muss.Dagegen
Kein klarer Vorschlag, wie dies an Codecs kommuniziert werden soll. - Es gibt keine Einschränkungen bei der Erstellung von Strings, die „für Surrogate reservierte“ Codepunkte falsch verwenden. Diese werden als „isolierte Surrogate“ bezeichnet. Die Codecs sollten das Lesen dieser aus Dateien verbieten, aber Sie könnten sie mit Zeichenketten-Literalen oder
unichr()erstellen.
Implementierung
Es gibt eine neue Definition
#define Py_UNICODE_SIZE 2
Um zu testen, ob UCS2 oder UCS4 verwendet wird, sollte das abgeleitete Makro Py_UNICODE_WIDE verwendet werden, das definiert ist, wenn UCS-4 verwendet wird.
Es gibt eine neue Konfigurationsoption
| –enable-unicode=ucs2 | konfiguriert ein schmales Py_UNICODE und verwendet wchar_t, wenn es passt |
| –enable-unicode=ucs4 | konfiguriert ein breites Py_UNICODE und verwendet wchar_t, wenn es passt |
| –enable-unicode | gleichbedeutend mit „=ucs2“ |
| –disable-unicode | entfernt die Unicode-Funktionalität vollständig. |
Es wird auch vorgeschlagen, dass eines Tages --enable-unicode standardmäßig die Breite von wchar_t Ihrer Plattform verwendet.
Windows-Builds werden eine Weile schmal sein, basierend auf der Tatsache, dass es wenige Anfragen nach breiten Zeichen gab, diese Anfragen hauptsächlich von Hardcore-Programmierern stammen, die ihre eigenen Python-Versionen kaufen können, und Windows selbst stark auf 16-Bit-Zeichen ausgerichtet ist.
Anmerkungen
Dieser PEP impliziert NICHT, dass Benutzer von Unicode eine 4-Byte-Kodierung für ihre Dateien auf der Festplatte oder im Netzwerk verwenden müssen. Er erlaubt ihnen nur, dies zu tun. ASCII ist beispielsweise immer noch eine legitime (7-Bit) Unicode-Kodierung.
Es wurde vorgeschlagen, dass es ein Modul geben sollte, das Surrogate in schmalen Python-Builds für Programmierer handhabt. Wenn jemand dies implementieren möchte, wird dies ein weiterer PEP sein. Es könnte auch mit Funktionen kombiniert werden, die andere Arten von Zeichen-, Wort- und Zeilen-basierten Indizierungen ermöglichen.
Abgelehnte Vorschläge
Mehr oder weniger der Status quo
Wir könnten offiziell sagen, dass Python-Zeichen 16-Bit sind und Programmierer auffordern, breite Zeichen in ihrer Anwendungslogik durch die Kombination von Surrogat-Paaren zu implementieren. Dies ist eine hohe Belastung, da die Emulation von 32-Bit-Zeichen, wenn sie vollständig in Python kodiert ist, wahrscheinlich sehr ineffizient ist. Außerdem wären diese abstrahierten Pseudo-Strings nicht als Eingabe für die reguläre Ausdrucks-Engine gültig.
„Speichereffizienter Unicode“-Typ
Eine andere Lösungsklasse besteht darin, eine effiziente interne Speicherung zu verwenden, dem Programmierer aber eine Abstraktion von breiten Zeichen zu präsentieren. Jede dieser Lösungen würde eine wesentlich komplexere Implementierung erfordern als die akzeptierte Lösung. Betrachten Sie zum Beispiel die Auswirkungen auf die reguläre Ausdrucks-Engine. Theoretisch könnten wir zu dieser Implementierung in der Zukunft wechseln, ohne Python-Code zu brechen. Ein zukünftiges Python könnte breite Python-Semantik auf schmalem Python „emulieren“. Guido ist derzeit nicht bereit, die Implementierung durchzuführen.
Zwei Typen
Wir könnten neben dem 16-Bit-Typ einen 32-Bit-Unicode-Typ einführen. Es gibt viel Code, der erwartet, dass es nur einen einzigen Unicode-Typ gibt.
Dieser PEP stellt die Lösung mit dem geringsten Aufwand dar. In den nächsten Jahren werden 32-Bit-Unicode-Zeichen häufiger vorkommen, was uns entweder davon überzeugen kann, dass wir eine ausgefeiltere Lösung benötigen, oder (andererseits) uns davon überzeugt, dass die einfache Mandatierung breiter Unicode-Zeichen eine geeignete Lösung ist. Derzeit sind die beiden auf dem Tisch liegenden Optionen: nichts tun oder dies tun.
Referenzen
Unicode-Glossar: http://www.unicode.org/glossary/
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0261.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT