Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung der chinesischen Verarbeitungsmethoden von Unicode und Python

Detaillierte Erläuterung der chinesischen Verarbeitungsmethoden von Unicode und Python

高洛峰
高洛峰Original
2017-03-20 09:06:561405Durchsuche

In der Python-Sprache war die Verarbeitung von UincodeStrings schon immer ein verwirrendes Problem. Vielen Python-Enthusiasten fällt es oft schwer, die Unterschiede zwischen Unicode, UTF-8 und vielen anderen Kodierungen herauszufinden. In diesem Artikel werden die relevanten Kenntnisse der chinesischen Verarbeitung von Unicode und Python vorgestellt. Werfen wir einen Blick mit dem Editor unten.

In der Python-Sprache war die Verarbeitung von Uincode-Strings schon immer ein verwirrendes Problem. Vielen Python-Enthusiasten fällt es oft schwer, die Unterschiede zwischen Unicode, UTF-8 und vielen anderen Kodierungen herauszufinden. Der Autor war einst Mitglied dieser „problematischen Gruppe“, aber nach mehr als einem halben Jahr harter Arbeit habe ich endlich einige Zusammenhänge herausgefunden. Es ist nun wie folgt organisiert und wird mit allen Kollegen geteilt. Gleichzeitig hoffe ich auch, dass dieser kurze Artikel mehr echte Experten dazu bringen kann, mitzumachen und gemeinsam unsere Python-Chinesisch-Umgebung zu verbessern.

Ein Teil der verschiedenen in diesem Artikel erwähnten Meinungen wird durch Konsultation der Daten eingeholt, andere werden vom Autor mithilfe verschiedener vorhandener codierter Daten mithilfe der Methode „Erraten und Verifizieren“ eingeholt. Der Autor glaubt, dass er wenig Talent und Wissen hat, und ich befürchte, dass darin viele Fehler verborgen sind. Es gibt viele Experten unter Ihnen, falls einer von Ihnen darin einen Fehler findet. Ich hoffe, Sie können mir einen Rat geben. Für den Autor ist es eine kleine Sache, sich selbst zu schämen, aber für andere ist es eine große Sache, eine falsche Meinung zu haben. Sie müssen sich also keine Sorgen um das Gesicht des Autors machen.

Abschnitt 1 Textkodierung und Unicode-Standard

Um Unicode-Strings zu erklären, müssen wir zunächst damit beginnen, was Unicode-Kodierung ist. Wie wir alle wissen, war die Textanzeige schon immer ein grundlegendes Problem, das Computeranzeigefunktionen lösen müssen. Der Computer ist nicht gebildet. Er betrachtet den Text tatsächlich als eine Reihe von „Bildern“, und jedes „Bild“ entspricht einem Zeichen. Wenn jedes Computerprogramm Text anzeigt, muss es eine Sammlung von „Bildern“ verwenden, die aufzeichnen, wie der Text „Bild“ angezeigt wird, die dem „Bild“ entsprechenden Daten für jedes Zeichen finden und das Wort auf die gleiche Weise „zeichnen“. . zum Bildschirm. Dieses „Bild“ wird „Schriftart“ genannt und die Sammlung der aufgezeichneten Schriftanzeigedaten wird „Zeichensatz“ genannt. Um die Programmsuche zu erleichtern, müssen die Schriftartdaten jedes Zeichens geordnet im Zeichensatz angeordnet sein und jedem Zeichen wird eine eindeutige ID zugewiesen. Diese ID ist die Kodierung des Zeichens. Wenn Computer Zeichendaten verarbeiten, wird diese Codierung immer zur Darstellung des Zeichens verwendet, das sie darstellen. Daher gibt ein Zeichensatz einen Satz von Zeichendaten an, die ein Computer verarbeiten kann. Offensichtlich geben verschiedene Länder unterschiedliche Zeichensatzgrößen an und auch die entsprechenden Zeichenkodierungen sind unterschiedlich.

In der Geschichte der Computer ist der ASCII-Zeichensatz der am weitesten verbreitete standardisierte Zeichensatz. Es handelt sich tatsächlich um einen Standard, der in den Vereinigten Staaten formuliert und für nordamerikanische Benutzer entwickelt wurde. Es verwendet eine 7-Bit-Kodierung und kann 128 Zeichen darstellen. Dieser Zeichensatz wurde schließlich von der ISO-Organisation offiziell als internationaler Standard übernommen und wird in verschiedenen Computersystemen häufig verwendet. Heutzutage enthält das BIOS aller PCs das Schriftartenmodell des ASCII-Zeichensatzes, was sich in seiner Beliebtheit zeigt.

Als Computer jedoch in verschiedenen Ländern weit verbreitet wurden, wurden die Einschränkungen der ASCII-Codierung deutlich: Der Zeichenraum ist wirklich begrenzt und kann nicht mehr Zeichen aufnehmen, aber die meisten Sprachen müssen die Anzahl der Zeichen verwenden weit mehr als 128. Um ihre eigenen Zeichen richtig zu handhaben, haben Beamte oder Privatpersonen in verschiedenen Ländern damit begonnen, ihre eigenen Zeichenkodierungssätze zu entwerfen, und schließlich entstanden viele Zeichenkodierungen für die Zeichen jedes Landes, wie beispielsweise die ISO-8859-1-Kodierung für Western Es gibt Codes der GB-Serie für vereinfachtes Chinesisch und SHIFT-JIS-Codes für Japanisch usw. Um gleichzeitig sicherzustellen, dass jeder neue Zeichensatz mit dem ursprünglichen ASCII-Text kompatibel ist, verwenden die meisten Zeichensätze ausnahmslos ASCII-Zeichen als ihre ersten 128 Zeichen und sorgen dafür, dass ihre Codierungen eins zu eins den ASCII-Codierungen entsprechen.

Auf diese Weise wird das Problem der Anzeige von Zeichen in verschiedenen Ländern gelöst, aber es bringt auch ein neues Problem mit sich: verstümmelte Zeichen. In verschiedenen Ländern und Regionen verwendete Zeichensätze unterliegen normalerweise keinen einheitlichen Spezifikationen, sodass die Kodierungen verschiedener Zeichensätze häufig nicht miteinander kompatibel sind. Die Kodierung desselben Wortes in zwei verschiedenen Zeichensätzen ist im Allgemeinen unterschiedlich, und die entsprechenden Zeichen derselben Kodierung in verschiedenen Zeichensätzen sind ebenfalls unterschiedlich. Ein in Kodierung A geschriebener Text wird auf einem System, das nur Kodierung B unterstützt, oft als Zeichenchaos angezeigt. Erschwerend kommt hinzu, dass die von verschiedenen Zeichensätzen verwendeten Kodierungslängen oft unterschiedlich sind. Programme, die nur Einzelbyte-Kodierung verarbeiten können, können Text oft nicht richtig verarbeiten, wenn sie auf Doppelbyte- oder sogar Mehrbyte-Kodierung stoßen " Problem. Dies machte die ohnehin schon chaotische Situation noch verwirrender.

Um diese Probleme ein für alle Mal zu lösen, haben viele große Unternehmen und Organisationen der Branche gemeinsam einen Standard vorgeschlagen, nämlich Unicode. Unicode ist eigentlich ein neues Zeichenkodierungssystem. Es kodiert jedes Zeichen im Zeichensatz mit einer zwei Byte langen ID-Nummer und definiert so einen Kodierungsraum, der bis zu 65536 Zeichen aufnehmen kann und alle heute in verschiedenen Ländern der Welt häufig verwendeten Wörter umfasst. Aufgrund sorgfältiger Überlegungen beim Entwurf der Codierung hat Unicode die Probleme verstümmelter Zeichen und „Halbwörter“, die durch andere Zeichensätze beim Datenaustausch verursacht werden, gut gelöst. Gleichzeitig berücksichtigten die Designer von Unicode die Tatsache, dass eine große Menge an Schriftdaten auch heute noch verschiedene von verschiedenen Ländern formulierte Kodierungen verwenden, und schlugen das Designkonzept vor, „Unicode als interne Kodierung zu verwenden“. Mit anderen Worten: Das Zeichenanzeigeprogramm verwendet weiterhin die ursprüngliche Codierung und den ursprünglichen Code, und die interne Logik der Anwendung verwendet Unicode. Wenn Text angezeigt werden soll, wandelt das Programm die Unicode-codierte Zeichenfolge immer in die ursprüngliche Codierung für die Anzeige um. Auf diese Weise muss nicht jeder das Schriftdatensystem neu gestalten, um Unicode zu verwenden. Um es von den von verschiedenen Ländern formulierten Kodierungen zu unterscheiden, bezeichnen die Designer von Unicode Unicode gleichzeitig als „breite Zeichenkodierungen“, während die von verschiedenen Ländern formulierten Kodierungen üblicherweise als „Multibyte-Kodierungen“ bezeichnet werden ( Multi-Bypes). Heute hat das Unicode-System eine erweiterte 4-Byte-Kodierung eingeführt und konvergiert schrittweise mit UCS-4, der ISO10646-Kodierungsspezifikation. Es besteht die Hoffnung, dass das ISO10646-System eines Tages zur Vereinheitlichung aller Textkodierungen auf der ganzen Welt verwendet werden kann .

Das Unicode-System erweckte gleich bei seiner Geburt große Hoffnungen und wurde schnell als von der ISO anerkannter internationaler Standard akzeptiert. Während des Promotionsprozesses von Unicode stieß es jedoch auf Widerstand europäischer und amerikanischer Benutzer. Der Grund für ihren Widerstand ist ganz einfach: Die von europäischen und amerikanischen Benutzern verwendeten Originalkodierungen sind Einzelbyte-lang, und die Doppelbyte-Unicode-Verarbeitungs-Engine kann die ursprünglichen Einzelbyte-Daten nicht verarbeiten, und wenn alle vorhandenen Einzelbyte-Texte dies benötigen zu konvertieren. Um es in Unicode zu konvertieren, wird der Arbeitsaufwand zu hoch sein. Wenn außerdem der gesamte Einzelbyte-kodierte Text in die Doppelbyte-Unicode-Kodierung konvertiert würde, würden alle Textdaten doppelt so viel Platz beanspruchen und alle Handler müssten neu geschrieben werden. Diesen Aufwand können sie nicht übernehmen.

Obwohl Unicode ein international anerkannter Standard ist, ist es für die Standardisierungsorganisation unmöglich, die Anforderungen europäischer und amerikanischer Benutzer, der größten Gruppe von Computerbenutzern, zu ignorieren. Nach Konsultationen zwischen allen Parteien wurde eine Variante von Unicode erstellt, nämlich UTF-8. UTF-8 ist ein Multibyte-Kodierungssystem. Die Kodierungsregeln lauten wie folgt:

1. Die UTF-8-Kodierung ist in vier Bereiche unterteilt:

Der erste Bereich ist die Einzelbyte-Kodierung,

Kodierungsformat ist: 0xxxxxxx;
entspricht Unicode: 0x0000 - 0x007f

Der zweite Bereich ist die Doppelbyte-Kodierung,

Kodierungsformat ist: 110xxxxx 10xxxxxx> entspricht Unicode: 0x0080 - 0x07ff

Die drei Bereiche sind Drei-Byte-Codierung, und das Codierungsformat von ist: 1110xxxx 10xxxxxxx 10xxxxxx

entspricht Unicode: 0x0800 - 0xffff

Die vier Bereiche sind Vier-Byte-Kodierung, Kodierungsformat ist: 11110xxx 10xxxxxxx 10xxxxxx 10xxxxxx

entspricht Unicode: 0x00010000 - 0x0001ffff

Die fünf Bereiche sind Fünf-Byte-Codierung und das Codierungsformat ist ist: 111110xx 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx

entsprechender Unicode: 0x00200000 - 0x03ffffff

Die sechs Bereiche haben eine Sechs-Byte-Kodierung. > Entspricht Unicode: 0x040000 00 - 0x7fffffffUnter diesen entsprechen der erste, zweite und dritte Bereich dem Doppelbyte-Codierungsbereich von Unicode, während der vierte Bereich für den vier Byte erweiterten Teil von Unicode ist (gemäß dieser Definition). , UTF -8 hat auch fünf und sechs Bezirke, aber ich habe sie nicht in der GNU-glibc-Bibliothek gefunden, ich weiß nicht warum); Fünf und sechs sind in der richtigen Reihenfolge angeordnet, und die Zeichen an den entsprechenden Positionen bleiben gleich als Unicode;

3. Unicode-Zeichen, die nicht angezeigt werden können, werden als 0 Bytes codiert, mit anderen Worten: Sie sind nicht in UTF-8 enthalten (dies ist die Aussage, die der Autor aus der GNU-C-Bibliothek erhalten hat

Kommentar

, die gemäß den UTF-8-Codierungsregeln möglicherweise nicht mit der tatsächlichen Situation übereinstimmt); Es ist nicht schwer herauszufinden, dass die 128 Codes im ersten Bereich tatsächlich ASCII-Codes sind. Daher kann die UTF-8-Verarbeitungs-Engine ASCII-Text direkt verarbeiten. Die Kompatibilität von UTF-8 mit der ASCII-Kodierung geht jedoch zu Lasten anderer Kodierungen. Beispielsweise waren chinesische, japanische und koreanische Zeichen ursprünglich grundsätzlich Doppelbyte-Kodierungen, aber ihre Positionen in der Unicode-Kodierung entsprechen den drei Bereichen in UTF-8, und jede Zeichenkodierung ist drei Bytes lang. Mit anderen Worten: Wenn wir alle vorhandenen, in China, Japan und Korea codierten Nicht-ASCII-Zeichentextdaten in die UTF-8-Codierung konvertieren, beträgt ihre Größe das 1,5-fache der Originalgröße.

Obwohl der Autor persönlich der Meinung ist, dass die Codierungsmethode von UTF-8 etwas unfair erscheint, hat sie das Übergangsproblem vom ASCII-Text zur Unicode-Welt gelöst und daher breite Anerkennung gefunden. Typische Beispiele sind XML und Java: Die Standardkodierung von XML-Text ist UTF-8, und Java-Quellcode kann tatsächlich in UTF-8-Zeichen geschrieben werden (JBuilder-Benutzer dürften beeindruckt sein). Außerdem gibt es in der Open-Source-Softwarewelt das bekannte GTK 2.0, das UTF-8-Zeichen als interne Kodierung verwendet.

Nachdem ich so viel gesagt habe, scheint das Thema etwas weit hergeholt zu sein: „Was hat das mit Python zu tun?“ in die Welt von Python Kommen Sie.

Abschnitt 2 Pythons Unicode-Kodierungssystem

Um mehrsprachigen Text korrekt verarbeiten zu können, führte Python nach Version 2.0 Unicode-Zeichenfolgen ein. Seitdem wurden Strings in der Python-Sprache in zwei Typen unterteilt: traditionelle Python-Strings, die schon lange vor Version 2.0 verwendet wurden, und neue Unicode-Strings. In der Python-Sprache verwenden wir die integrierte unicode()-Funktion , um einen herkömmlichen Python-String zu „dekodieren“, um einen Unicode-String zu erhalten, und verwenden dann die encode()-Methode des Unicode-Strings, um diesen zu dekodieren Der Unicode-String wird in einen traditionellen Python-String „kodiert“. Der obige Inhalt muss jedem Python-Benutzer bekannt sein. Aber wussten Sie, dass der Unicode-String von Python kein echter „Unicode-codierter String“ ist, sondern seinen eigenen einzigartigen Regeln folgt? Der Inhalt dieser Regel ist sehr einfach:

1 Die Python-Unicode-Kodierung von ASCII-Zeichen ist dieselbe wie ihre ASCII-Kodierung. Mit anderen Worten, der ASCII-Text in Pythons Unicode-Zeichenfolge ist immer noch eine Einzelbyte-Kodierung.

2 Die Kodierung anderer Zeichen als ASCII-Zeichen ist Unicode Eine Zwei-Byte- (oder Vier-Byte-)Kodierung der Standardkodierung. (Der Autor vermutet, dass der Grund, warum die Python-Community einen so seltsamen Standard formuliert hat, darin besteht, die Universalität von ASCII-Strings sicherzustellen.)

Normalerweise werden in Python-Anwendungen Unicode-Strings verwendet interne Verarbeitung, während die Anzeigearbeit des Terminals durch herkömmliche Python-Zeichenfolgen erledigt wird (tatsächlich kann die print-Anweisung von Python überhaupt keine Doppelbyte-Unicode-codierten Zeichen ausdrucken). In der Python-Sprache sind traditionelle Python-Strings sogenannte „Multi-Byte-codierte“ Strings, die zur Darstellung verschiedener Strings verwendet werden, die in bestimmte Zeichensatzcodierungen (wie GB, BIG5, KOI8-R, JIS, ISO-8859-1 und natürlich UTF-8); und Python-Unicode-Strings sind Strings mit „breiter Zeichenkodierung“, die Unicode-Daten darstellen, die aus einer bestimmten Zeichensatzkodierung „dekodiert“ sind. Normalerweise verarbeitet eine Python-Anwendung, die Unicode-Codierung verwenden muss, Zeichenfolgendaten häufig auf die folgende Weise:


def foo(string, encoding = "gb2312"):
# 1. convert multi-byte string to wide character string
u_string = unicode(string, encoding)

# 2. do something
...

# 3. convert wide character string to printable multi-byte string
return u_string.encode(encoding)


Wir kann ein Beispiel nennen: Python-Kollegen, die häufig PyGTK2 für die 🎜>


Wenn eine Anweisung wie diese ausgeführt wird, erscheint auf dem Terminal eine Warnung wie diese:
import pygtk
pygtk.require('2.0')
import gtk

main = gtk.Window() # create a window
main.set_title("你好") # NOTICE!


Und der Titel des Programmfensters wird nicht auf „Hallo“ gesetzt, aber wenn der Benutzer den chinesischen Codec installiert und den letzten Satz oben ändert in:

Error converting from UTF-8 to 'GB18030': 转换输入中出现无效字符序列


Dann wird der Titel des Programmfensters korrekt auf „Hallo“ gesetzt. Warum ist das so?
u_string = unicode('你好','gb2312')
main.set_title(u_string)

Der Grund ist einfach. Die Methode gtk.Window.set_title() behandelt die empfangene Titelzeichenfolge immer als Unicode-Zeichenfolge. Wenn das PyGTK-System die main.set_title()-Anfrage des Benutzers empfängt, verarbeitet es die erhaltene Zeichenfolge irgendwo wie folgt:


Wir sehen, dass die Zeichenfolge title_unicode_string in eine neue Zeichenfolge innerhalb des Programms „codiert“ wird: real_title_string. Offensichtlich ist dieser real_title_string ein traditioneller Python-String und seine Codierung ist UTF-8. Im vorherigen Abschnitt erwähnte der Autor, dass die in GTK2 intern verwendeten Zeichenfolgen in UTF-8 codiert sind, sodass das GTK2-Kernsystem den Titel nach dem Empfang von real_title_string korrekt anzeigen kann.
class Window(gtk.Widget):
...
def set_title(self, title_unicode_string):
...
# NOTICE! unicode -> multi-byte utf-8
real_title_string = title_unicode_string.encode('utf-8')
...
# pass read_title_string to GTK2 C API to draw the title
...

Was passiert also, wenn der vom Benutzer eingegebene Titel eine ASCII-Zeichenfolge ist (zum Beispiel: „Hallo Welt“)? Wenn wir uns an die Definitionsregeln von Python-Unicode-Strings erinnern, ist es nicht schwer festzustellen, dass, wenn die Benutzereingabe ein ASCII-String ist, das Ergebnis, das durch die Neucodierung erhalten wird, er selbst ist. Mit anderen Worten: Wenn der Wert von title_unicode_string ein ASCII-String ist, sind die Werte von real_title_string und title_unicode_string genau gleich. Ein ASCII-String ist auch ein UTF-8-String und kann problemlos an das GTK2-System übergeben werden.

Die oben genannten Beispiele beziehen sich auf PyGTK2 unter Linux, aber ähnliche Probleme treten nicht nur in PyGTK auf. Zusätzlich zu PyGTK werden auch verschiedene aktuelle Python-gebundene Grafikpakete wie PyQT, Tkinter usw. mehr oder weniger auf Probleme im Zusammenhang mit der Unicode-Verarbeitung stoßen.

Nachdem wir den Unicode-String-Kodierungsmechanismus von Python herausgefunden haben, ist die Frage, die wir am meisten wissen wollen, immer noch ungelöst: Wie können wir dafür sorgen, dass Python die Verwendung von Unicode zur Verarbeitung von Chinesisch unterstützt? Wir werden dieses Problem im nächsten Abschnitt erläutern.

Abschnitt 3: So stellen Sie sicher, dass Pythons Unicode-Zeichenfolge Chinesisch unterstützt

Nachdem Sie den Titel dieses Abschnitts gelesen haben, sind einige Python-Kollegen möglicherweise etwas missbilligend: „Warum tun wir das?“ Müssen wir Unicode verwenden, um Chinesisch zu verarbeiten? Sind wir normalerweise nicht gut darin, traditionelle Python-Zeichenfolgen zu verwenden? Wenn es sich jedoch um einige erweiterte Zeichenfolgenoperationen handelt, wie z. B. den Abgleich von regulären Ausdrücken mit multinationalen Zeichen, Textbearbeitung, Ausdrucksanalyse usw., handelt es sich um eine große Anzahl gemischter Einzelbyte- und Mehrbyte-Operationen Texte. Der Vorgang wäre sehr mühsam, wenn die herkömmliche Zeichenfolgenverarbeitung verwendet würde. Außerdem können herkömmliche Strings niemals das verdammte „Halbwort“-Problem lösen. Und wenn wir Unicode verwenden können, können diese Probleme leicht gelöst werden. Daher müssen wir uns dem Problem der chinesischen Unicode-Verarbeitung stellen und versuchen, es zu lösen. Aus der Einführung im vorherigen Abschnitt wissen wir, dass Sie, wenn Sie den Unicode-Mechanismus von Python zum Verarbeiten von Zeichenfolgen verwenden möchten, über einen Code verfügen, der chinesische Multibyte-Codierung (einschließlich GB-Codierungsserien) kombinieren kann BIG5-Serie) und Unicode Das Kodierungs-/Dekodierungsmodul führt eine bidirektionale Konvertierung der Kodierung durch. Gemäß der Python-Terminologie wird ein solches Kodierungs-/Dekodierungsmodul Codec genannt. Die nächste Frage lautet also: Wie schreiben wir einen solchen Codec?

Wenn der Unicode-Mechanismus von Python im Python-Kern fest codiert ist, wird das Hinzufügen eines neuen Codecs zu Python eine mühsame Aufgabe sein. Glücklicherweise sind die Entwickler von Python nicht so dumm. Sie bieten einen äußerst erweiterbaren Mechanismus, mit dem sich problemlos neue Codecs zu Python hinzufügen lassen.

Das Unicode-Verarbeitungsmodul von Python besteht aus drei wichtigsten Komponenten: Eine ist die Datei codecs.py, die andere ist das Codierungsverzeichnis und die dritte ist die Datei aliases.py. Die ersten beiden befinden sich im Installationsverzeichnis der Python-Systembibliothek (wenn es sich um eine Win32-Distribution handelt, befindet sie sich im Verzeichnis $PYTHON_HOME/lib/; wenn es sich um Red Hat Linux handelt, befindet sie sich im Verzeichnis /usr/lib/python -version/-Verzeichnis. Andere Systeme können es auf ähnliche Weise finden, und das letzte befindet sich im Verzeichnis „encodings“. Als nächstes erklären wir diese drei.

Werfen wir zunächst einen Blick auf die Datei codecs.py. Diese Datei definiert die Schnittstelle, die ein Standard-Codec-Modul haben sollte. Der spezifische Inhalt kann in Ihrer eigenen Python-Distribution gefunden werden, daher werde ich hier nicht auf Details eingehen. Gemäß der Definition der Datei codecs.py sollte ein vollständiger Codec mindestens drei Klassen und eine Standardfunktion haben:

1 Codec-Klasse Zweck:

wird verwendet, um die vom Benutzer übergebenen Pufferdaten (einen Puffer) als herkömmliche Python-Zeichenfolge zu behandeln und sie

in die entsprechende Unicode-Zeichenfolge zu „dekodieren“. Eine vollständige Codec-Klassendefinition muss zwei Methoden bereitstellen: Codec.decode() und

Codec.encode():

Codec.decode(input, <a href="http%20:%20//www.php.cn/wiki/222.html" target="_blank">errors</a>

= "strict")

Codec.decode(input, <a href="http://www.php.cn/wiki/222.html" target="_blank">errors</a> = "strict") wird verwendet, um die Eingabedaten als traditionelle Python-Zeichenfolge zu behandeln und „dekodieren“ Sie es in die entsprechende Unicode-Zeichenfolge.

Parameter:

Eingabe: Eingabepuffer (kann eine Zeichenfolge oder ein beliebiges Objekt sein, das in eine Zeichenfolgendarstellung konvertiert werden kann)

Fehler: Wenn bei der Verarbeitung ein Konvertierungsfehler auftritt Optionen. Sie können aus den folgenden drei Werten wählen:

strict (Standardwert): Wenn ein Fehler auftritt, wird eine UnicodeError-Ausnahme ausgelöst.

replace: Wenn ein Fehler auftritt, wird eine Standard-Unicode-Kodierung ausgelöst stattdessen ausgewählt. ;

ignorieren: Wenn ein Fehler auftritt, wird dieses Zeichen ignoriert und die Analyse der verbleibenden Zeichen wird fortgesetzt.

Rückgabewert:

Eine konstante Liste (Tupel): Das erste Element ist die konvertierte Unicode-Zeichenfolge und das letzte Element ist die Länge der Eingabedaten.

Codec.encode(input, errors = "strict") wird verwendet, um die Eingabedaten als Unicode-String zu behandeln und sie in den entsprechenden traditionellen Python-String zu „kodieren“.

Parameter:

Eingabe: Eingabepuffer (normalerweise ein Unicode-String)

Fehler: Verarbeitungsoptionen, wenn Konvertierungsfehler auftreten. Die Wertregeln sind die gleichen wie bei der Methode Codec.decode().

Rückgabewert:

Eine konstante Liste (Tupel): Das erste Element ist die konvertierte traditionelle Python-Zeichenfolge und das letzte Element ist die Länge der Eingabedaten.

2. StreamReader-Klasse (sollte normalerweise von der Codec-Klasse erben)

用于分析文件输入流。提供所有对文件对象的读取操作,如readline()方法等。

3、StreamWriter类(通常应该继承自Codec类)

用于分析文件输出流。提供所有对文件对象的写入操作,如writeline()方法等。

5、getregentry()函数

即“GET REGistry ENTRY”之意,用于获取各个Codec文件中定义的四个关键函数。其函数体统一为:


def getregentry():
return tuple(Codec().encode,Codec().decode,StreamReader,StreamWriter)


在以上提到的所有四个类中,实际上只有Codec类和getregentry()函数是必须提供的。必须提供前者是因为它是实际提供转换操作的模块;而后者则是Python系统获得Codec定义的标准接口,所以必须存在。至于StreamReader和StreamWriter,理论上应该可以通过继承codecs.py中的StreamReader和StreamWriter类,并使用它们的默认实现。当然,也有许多codec中将这两个类进行了改写,以实现一些特殊的定制功能。

接下来我们再说说encodings目录。顾名思义,encodings目录就是Python系统默认的存放所有已经安装的codec的地方。我们可以在这里找到所有Python发行版自带的codecs。习惯上,每一个新的codec都会将自己安装在这里。需要注意的是,Python系统其实并不要求所有的codec都必须安装于此。用户可以将新的codec放在任何自己喜欢的位置,只要Python系统的搜索路径可以找得到就行。

仅仅将自己写的codec安装在Python能够找到的路径中还不够。要想让Python系统能找到对应的codec,还必须在Python中对其进行注册。要想注册一个新的codec,就必须用到encodings目录下的aliases.py文件。这个文件中只定义了一个哈希表aliases,它的每个键对应着每一个codec在使用时的名称,也就是unicode()内建函数的第二个参数值;而每个键对应的值则是一个字符串,它是这个codec对应的那个处理文件的模块名。比如,Python默认的解析UTF-8的codec是utf_8.py,它存放在encodings子目录下,则aliases哈希表中就有一项表示其对应关系:

'utf-8' : 'utf_8', # the <a href="http://www.php.cn/code/8212.html" target="_blank">module</a> `utf_8' is the codec <a href="http://www.php.cn/wiki/125.html" target="_blank">for</a> UTF-8

同理,如果我们新写了一个解析‘mycharset'字符集的codec,假设其编码文件为mycodec.py,存放在$PYTHON_HOME/lib/site-packages/mycharset/目录下,则我们就必须在aliases哈希表中加入这么一行:

'mycharset' : 'mycharset.mycodec',

这里不必写出mycodec.py的全路径名,因为site-packages目录通常都在Python系统的搜索路径之中。

Python解释器在需要分析Unicode字符串时,会自动加载encodings目录下的这个aliases.py文件。如果mycharset已经在系统中注册过,则我们就可以像使用其它内建的编码那样使用我们自己定义的codec了。比如,如果按照上面的方式注册了mycodec.py,则我们就可以这样写:


my_unicode_string = unicode(a_multi_byte_string, &#39;mycharset&#39;)

print my_unicode_string.encode(&#39;mycharset&#39;)


现在我们可以总结一下要编写一个新的codec一共需要那些步骤:

首先,我们需要编写一个自己的codec编码/解码模块;

其次,我们要把这个模块文件放在一个Python解释器可以找到的地方;

最后,我们要在encodings/aliases.py文件中对其进行注册。

从理论上说,有了这三步,我们就可以将自己的codec安装到系统中去了。不过这样还不算完,还有一个小问题。有时候,我们出于种种原因,不希望随便修改自己的系统文件(比如,一个用户工作在一个集中式的系统中,系统管理员不允许别人对系统文件进行修改)。在以上介绍的步骤中,我们需要修改aliases.py文件的内容,这是一个系统文件。可如果我们不能修改它,难道我们就不能添加新的codec吗?不,我们当然有办法。

这个办法就是:在运行时修改encodings.aliases.aliases哈希表的内容。

还是使用上面那个假设,如果用户工作系统的管理员不允许用户把mycodec.py的注册信息写入aliases.py,那么我们就可以如此处理:

1、将mycodec.py放在一个目录下,比如/home/myname/mycharset/目录;

2、这样编写/home/myname/mycharset/init.py文件:


import encodings.aliases
# update aliases hash map
encodings.aliases.aliases.update({/
&#39;mycodec&#39; : &#39;mycharset.mycodec&#39;,/
}}


以后每次要使用Python时,我们可以将/home/myname/加入搜索路径,并且在使用自己的codec时预先执行:

import mycharset # execute the script in mycharset/init.py

这样我们就可以在不改动原有系统文件的情况下使用新的codecs了。另外,如果借助Python的site机制,我们还可以让这个import工作自动化。如果大家不知道什么是site,就请在自己的Python交互环境中运行:


import site
print site.doc


浏览一下site模块的文档,即可明白个中技巧。如果大家手头有Red Hat Linux v8,v9,还可以参考一下Red Hat的Python发行版中附带的日文codec,看看它是如何实现自动加载的。也许不少同道可能找不到这个日文的codec在哪里,这里列出如下:


  Red Hat Linux v8:在/usr/lib/python2.2/site-package/japanese/目录下;
  Red Hat Linux v9:在/usr/lib/python2.2/lib-dynload/japanese/目录下;


提示:请Red Hat用户注意site-packages目录下的japanese.pth文件,结合site模块的文档,相信马上就能豁然开朗。

结束语

记得当初笔者在Dohao论坛上夸下海口:“如果可以的话,我可以为大家编写一个(中文模块)”,现在回想起来,不禁为自己当初的不知天高地厚而汗颜。一个把自己所有的的时间都花在学习上,一个学期只学七门课程,还落得个两门课不及格的傻瓜研究生,哪里有什么资格在大家面前如此嚣张。现如今,第二个学期由于这两门课的缘故负担陡增(十门课呀!),家中老父老母还眼巴巴地等着自己的儿子能给他们挣脸。要想在有限的时间之内,既保证学习,又保证工作(我要承担导师的课程辅导工作,同时还有一个学校的教学改革方案需要我在其中挑大梁),已经是疲于应付,再加上一个中文模块……唉,请恕笔者分身乏术,不得不食言。

因此,笔者斗胆,在此和盘托出自己这半年以来的心得,只希望能够找到一批,不,哪怕是一个也好,只要是对这个项目感兴趣的同道中人,能够接下笔者已经整理出来的知识,把一个完整的(至少应该包含GB、BIG5、笔者个人认为甚至还应包括HZ码)中文模块编写出来,贡献给大家(不论是有偿的还是无偿的),那就是我们广大Python爱好者之福了。另外,Python的发行版至今尚未包括任何中文支持模块。既然我等平日深爱Python,如果我们的工作能因此为Python的发展做出一点贡献,何乐而不为呢?

附录 几个小小提示

1、LUO Jian兄已经编写了一个非常不错的中文模块(Dohao上有链接,文件名是showfile.zip,这个模块比我已经写完的草稿版本要快得多),同时支持GB2312和GB18030编码,可惜不支持BIG5。如果大家有兴趣,可以下载这个模块研究一下;

2、和其它字符集编码相比,中文模块有其特殊性,那就是其海量的字符数目。一些相对较小的字符集还好说,比如GB2312,可以利用哈希表查找。而对于巨大的GB18030编码,如果简单地将所有数据制成一个特大的编码对照表,则查询速度会慢得让人无法容忍(笔者在编写模块时最头疼的就是这一点)。如果要编写一个速度上能让人满意的codec,就必须考虑设计某种公式,能够通过简单地运算从一种编码推算出另一种来,或者至少能推算出它的大概范围。这就要求程序员要能对整个编码方案做统计,设法找到规律。笔者认为,这应该是编写中文模块时的最大难点。或许是数学功底实在太差的缘故,笔者费尽心机也未能找出一个规律来。希望能有数学高手不吝赐教;

3、中文编码分为两大派系:GB和BIG5。其中GB又分为GB2312、GBK和、GB18030三种编码,而BIG5也分为BIG5和BIG5-HKSCS两种(分别对应原始的BIG5和香港扩展版本)。虽然同一派系的编码可以向下兼容,但考虑到其字符数目庞大,为了加快查找速度,笔者个人认为还是将它们分开编码比较合理。当然,如果能够找到对应字符集的转换公式,则这种分离就没有必要了;

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der chinesischen Verarbeitungsmethoden von Unicode und Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn