UnicodeとPythonの中国語処理方法を詳しく解説

高洛峰
リリース: 2017-03-20 09:06:56
オリジナル
1366 人が閲覧しました

Python 言語では、Uincodestringの処理は常に混乱を招く問題でした。多くの Python 愛好家は、Unicode、UTF-8、およびその他の多くのエンコーディングの違いを理解するのに苦労することがよくあります。この記事ではUnicodeとPythonの中国語処理に関する関連知識を紹介します。以下のエディターで見てみましょう

Python 言語では、Uincode 文字列の処理は常に紛らわしい問題です。多くの Python 愛好家は、Unicode、UTF-8、およびその他の多くのエンコーディングの違いを理解するのに苦労することがよくあります。筆者もかつてはこの「やっかいなグループ」の一員でしたが、半年以上の努力を経て、ようやく関係性の一部が分かりました。現在は以下のように整理され、同僚全員で共有されています。同時に、この短い記事によって、より多くの本物の専門家が参加し、共同で Python 中国語環境を改善できることを願っています。

この記事で言及されているさまざまな意見は、一部はデータを参照することによって得られ、一部は著者が既存のさまざまなコード化されたデータを使用して「推測と検証」方法を使用して得たものです。著者は自分には才能も知識もほとんどないと思っており、間違いがたくさん隠れているのではないかと心配しています。読者の中に専門家もたくさんいますので、もし間違いを見つけた方がいらっしゃいましたら、専門家の方からアドバイスをいただければ幸いです。著者自身が恥ずかしいことは些細なことですが、他人が間違った意見を持つことは一大事なので、著者の面子を気にする必要はありません。

セクション 1 テキストエンコーディングと Unicode 標準

Unicode 文字列を説明するには、まず Unicode エンコーディングとは何なのかから始める必要があります。誰もが知っているように、テキスト表示は常にコンピュータの表示機能が解決しなければならない基本的な問題です。コンピューターは読み書き能力がありません。実際には、テキストを一連の「絵」として認識し、それぞれの「絵」が文字に対応します。各コンピュータプログラムがテキストを表示するときは、テキストの「画像」がどのように表示されるかを記録する「画像」のコレクションを使用し、各文字の「画像」に対応するデータを見つけて、同じ方法で単語を「描画」する必要があります。 . 画面に。この「絵」を「フォント」と呼び、記録されたフォント表示データの集合を「

文字セット」と呼びます。プログラムの検索を容易にするために、各文字のフォント データは文字セット内に整然と配置されている必要があり、各文字には固有の ID が割り当てられます。この ID が文字のエンコードになります。コンピューターが文字データを処理するとき、このエンコーディングは常に、それが表す文字を表すために使用されます。したがって、文字セットは、コンピュータが処理できる文字データのセットを指定します。当然のことながら、国が異なれば指定される文字セット サイズも異なり、対応する文字エンコーディングも異なります。

コンピューターの歴史の中で、最も広く使用されている標準化された文字セットは ASCII 文字セットです。これは実際には米国で策定され、北米のユーザー向けに開発された規格です。 7 バイナリ ビット エンコーディングを使用し、128 文字を表現できます。この文字セットは最終的に ISO 組織によって国際標準として正式に採用され、さまざまなコンピュータ システムで広く使用されています。現在では、すべての PC の BIOS に ASCII 文字セットのフォント モデルが含まれており、その人気は明らかです。

しかし、コンピューターがさまざまな国で広く普及すると、ASCII エンコーディングの限界が明らかになりました。その文字スペースは非常に限られており、それ以上の文字を収容することはできませんが、ほとんどの言語で使用する必要がある文字数ははるかに遠くなります。 128以上。独自の文字を正しく処理するために、さまざまな国の役人や個人が独自の文字エンコーディング セットを設計する作業を開始し、最終的には、西洋文字の ISO-8859-1 エンコーディングなど、各国の文字に対応する多くの文字エンコーディングが登場しました。欧文文字には、簡体字中国語の GB シリーズ コード、日本語の SHIFT-JIS コードなどがあります。同時に、新しい各文字セットが元の ASCII テキストと互換性があることを保証するために、ほとんどの文字セットは常に最初の 128 文字として ASCII 文字を使用し、そのエンコードを ASCII エンコードに 1 対 1 で対応させます。

このようにして、各国の文字表示の問題は解決しましたが、文字化けという新たな問題も発生しました。さまざまな国や地域で使用される文字セットは通常、統一された仕様に拘束されていないため、さまざまな文字セットのエンコーディングが互いに互換性がないことがよくあります。 2 つの異なる文字セットでの同じ単語のエンコーディングは通常異なり、異なる文字セットでの同じエンコーディングの対応する文字も異なります。エンコーディング A で書かれたテキストは、エンコーディング B のみをサポートするシステムでは、文字がごちゃ混ぜになって表示されることがよくあります。さらに悪いことに、さまざまな文字セットで使用されるエンコーディングの長さが異なることがよくあります。シングルバイト エンコーディングのみを処理できるプログラムでは、悪名高い「ハーフワード」が発生すると、テキストを正しく処理できないことがよくあります。 " 問題。これにより、ただでさえ混沌とした状況がさらに混乱した。

これらの問題をきっぱり解決するために、業界の多くの大企業や組織が共同で Unicode という標準を提案しました。 Unicode は実際には新しい文字エンコーディング システムです。文字セット内の各文字を 2 バイト長の ID 番号でエンコードし、最大 65536 文字を収容できるコーディング スペースを定義し、世界のさまざまな国のエンコーディングで一般的に使用されるすべての単語を含めます。エンコーディングの設計における慎重な配慮により、Unicode はデータ交換時に他の文字セットによって引き起こされる文字化けや「ハーフワード」の問題をうまく解決しました。同時に、Unicode の設計者は、現在でも多くのフォントデータが各国で策定されたさまざまなエンコーディングを使用している現実を十分に考慮し、「内部エンコーディングとして Unicode を使用する」という設計コンセプトを打ち出しました。つまり、文字表示プログラムでは元のエンコーディングとコードがそのまま使用され、アプリケーションの内部ロジックでは Unicode が使用されます。テキストを表示する場合、プログラムは常に Unicode でエンコードされた文字列を元のエンコードに変換して表示します。この方法では、誰もが Unicode を使用するためにフォント データ システムを再設計する必要がありません。同時に、各国で策定されたエンコーディングと区別するために、Unicode の設計者は Unicode を「ワイド文字エンコーディング」(ワイド文字エンコーディング)と呼び、各国で策定されたエンコーディングを慣例的に「マルチ文字エンコーディング」と呼びます。 -バイトエンコーディング」(マルチバイト)。エンコーディング)。現在、Unicode システムは 4 バイトの拡張エンコーディングを導入しており、ISO10646 エンコーディング仕様である UCS-4 に徐々に収束しつつあります。いつの日か ISO10646 システムを使用して世界中のすべてのテキスト エンコーディングが統一されることが期待されています。 。

Unicode システムは誕生するとすぐに大きな期待を集め、すぐに ISO によって認められた国際標準として受け入れられました。しかし、Unicode の推進過程で、ヨーロッパとアメリカのユーザーからの反対に遭いました。彼らの反対の理由は非常に単純です。ヨーロッパとアメリカのユーザーが使用している元のエンコーディングはシングルバイト長であり、ダブルバイト Unicode 処理エンジンは元のシングルバイト データを処理できず、既存のシングルバイト テキストがすべて必要な場合です。 Unicodeに変換するには負荷がかかりすぎます。さらに、すべての 1 バイトでエンコードされたテキストが 2 バイトの Unicode エンコードに変換された場合、すべてのテキスト データは 2 倍のスペースを占有し、すべてのハンドラーを書き直す必要があります。彼らはこの出費を受け入れることができません。

Unicode は国際的に認められた標準ですが、標準化団体が最大のコンピューター ユーザー グループであるヨーロッパとアメリカのユーザーの要件を考慮しないことは不可能です。そこで、関係者全員による協議の結果、Unicode のバリアント バージョンである UTF-8 が作成されました。 UTF-8 はマルチバイト エンコーディング システムであり、そのエンコーディング ルールは次のとおりです:

1. UTF-8 エンコーディングは 4 つの領域に分割されます: 1 つの領域はシングルバイト エンコーディングです。

エンコード形式は次のとおりです: 0xxxxxxx;

Unicode に対応します: 0x0000 - 0x007f 2 番目の領域は 2 バイトエンコードです


エンコード形式は 110xxxxx 10xxxxxx; Unicode に対応: 0x0080 - 0x07ff

3番目の領域は3バイトエンコードです​​

エンコード形式は次のとおりです: 1110xxxx 10xxxxxxx 10xxxxxx

対応するUnicode: 0x0800 - 0xffff

は 4 バイトのエンコードです、

エンコード形式は次のとおりです: 11110xxx 10xxxxxxx 10xxxxxx 10xxxxxx

は Unicode に対応します: 0x00010000 - 0x0001ffff

5 つの領域は 5 バイトのエンコードであり、

エンコード形式は次のとおりです: 110xx 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx

に対応Unicode: 0x00200000 - 0x03ffffff

6 つの領域は 6 バイトのエンコードであり、

エンコード形式は次のとおりです: 111110x 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx

Unicode: 0 に対応します。 x04000000 - 0x7ffffffff

その中で、1番目、2番目3 番目の領域は Unicode の 2 バイトのエンコード領域に対応し、4 番目の領域は Unicode の 4 バイトの拡張部分に対応します (この定義によれば、UTF-8 にも 5 つと 6 つの領域がありますが、著者はGNU glibc ライブラリでは見つかりません。理由はわかりません) 2. 各領域は次のとおりです: 2、3、4、5、6 が順番に配置され、対応する位置に文字が配置されます。 Unicode と同じままです。 3. 表示できない Unicode 文字は 0 バイトとしてエンコードされます。つまり、それらは UTF-8 に含まれません (これは、作成者が GNU C から得た声明です)。ライブラリ

コメント

(実際の状況と一致しない可能性があります);

UTF-8 エンコード規則によれば、最初の領域の 128 個のコードが実際には ASCII コーディングであることを見つけるのは難しくありません。したがって、UTF-8 処理エンジンは ASCII テキストを直接処理できます。ただし、UTF-8 と ASCII エンコーディングとの互換性は、他のエンコーディングを犠牲にして実現されます。たとえば、もともと中国語、日本語、韓国語の文字は基本的に 2 バイトのエンコードでしたが、Unicode エンコードにおける位置は UTF-8 の 3 つの領域に対応し、各文字エンコードの長さは 3 バイトになります。つまり、中国、日本、韓国でエンコードされた既存の非 ASCII 文字テキスト データをすべて UTF-8 エンコードに変換すると、そのサイズは元のサイズの 1.5 倍になります。

作者は個人的に、UTF-8 のエンコード方法は少し不公平に思えると思っていますが、ASCII テキストから Unicode の世界への移行の問題を解決したため、広く認知されました。典型的な例は XML と Java です。XML テキストのデフォルトのエンコーディングは UTF-8 であり、Java ソース コードは実際に UTF-8 文字で記述することができます (JBuilder ユーザーはきっと感動するはずです)。オープン ソース ソフトウェアの世界ではよく知られている GTK 2.0 もあり、これは内部エンコードとして UTF-8 文字を使用します。

ここまで言うと、この話題は少し遠いところにあるように思えますが、多くの Python 愛好家は「これは Python と何の関係があるのでしょう?」と心配し始めているかもしれません。さて、ここで Python の世界に目を向けましょう。 。

セクション 2 Python の Unicode エンコーディング システム

多言語テキストを正しく処理するために、Python はバージョン 2.0 以降 Unicode 文字列を導入しました。それ以来、Python 言語の文字列は、バージョン 2.0 より前から長い間使用されてきた伝統的な Python 文字列と、新しい Unicode 文字列の 2 種類に分類されるようになりました。 Python 言語では、unicode() 組み込み関数 を使用して従来の Python 文字列を「デコード」して Unicode 文字列を取得し、次に Unicode 文字列の encode() メソッドを通じてこの Unicode 文字列を「デコード」します。 」、それを従来の Python 文字列に「エンコード」します。上記の内容は、すべての Python ユーザーにとって馴染みのあるものであるはずです。しかし、Python の Unicode 文字列は真の「Unicode でエンコードされた文字列」ではなく、独自の独自の規則に従っていることをご存知ですか。このルールの内容は非常に単純です:

1. ASCII 文字の Python Unicode エンコードは、その ASCII エンコードと同じです。 言い換えれば、Python の Unicode 文字列内の ASCII テキストは依然として 1 バイト長のエンコーディングです。

2. ASCII 文字以外の文字のエンコーディングは、2 バイト (または 4 バイト) の Unicode 標準エンコーディングです。コーディング。 (Pythonコミュニティがこのような奇妙な標準を策定した理由は、ASCII文字列の普遍性を確保するためではないかと筆者は推測しています)

通常、Pythonアプリケーションでは内部処理にUnicode文字列が使用され、端末の表示作業は従来の Python 文字列によって完成されます (実際、Python の

print ステートメントは、2 バイトの Unicode エンコード文字をまったく出力できません)。 Python 言語では、従来の Python 文字列はいわゆる「マルチバイト エンコードされた」文字列であり、特定の文字セット エンコード (GB、BIG5、KOI8-R、JIS、 ISO-8859-1、そしてもちろん UTF-8)、Python Unicode 文字列は「ワイド文字エンコーディング」文字列であり、特定の文字セット エンコーディングから「デコードされた」Unicode データを表します。したがって、通常、Unicode エンコーディングを必要とする Python アプリケーションは、次の方法で文字列データを処理することがよくあります:


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)
ログイン後にコピー


例を挙げることができます: Red Hat

Linux 環境でよく使用されます XWindow を実行している Python の同僚PyGTK2 での プログラミング は、ずっと前にこの状況を発見していたかもしれません: 次のステートメントを直接記述すると:


import pygtk
pygtk.require('2.0')
import gtk

main = gtk.Window() # create a window
main.set_title("你好") # NOTICE!
ログイン後にコピー


このようなステートメントは、このような警告を実行するときにターミナルに表示されます:

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

とプログラム ウィンドウのタイトルは「Hello」に設定されませんが、ユーザーが中国語コーデックをインストールし、上記の最後の文を


u_string = unicode('你好','gb2312')
main.set_title(u_string)
ログイン後にコピー


に変更すると、プログラム ウィンドウのタイトルが正しく設定されます。 「こんにちは」に。どうしてこれなの?

理由は簡単です。 gtk.Window.set_title() メソッドは、受け取ったタイトル文字列を常に Unicode 文字列として扱います。 PyGTK システムは、ユーザーの main.set_title() リクエストを受け取ると、次のように取得した文字列をどこかで処理します。


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
...
ログイン後にコピー


文字列 title_unicode_string がプログラム内で処理され、「Encoding」が新しい文字列になることがわかります。 : real_title_string。明らかに、この real_title_string は従来の Python 文字列であり、そのエンコードは UTF-8 です。前のセクションで、作者は GTK2 の内部で使用される文字列が UTF-8 でエンコードされているため、GTK2 コア システムは real_title_string を受信した後にタイトルを正しく表示できると述べました。

それでは、ユーザーが入力したタイトルが ASCII 文字列 (例: "hello world") の場合はどうなるでしょうか? Python Unicode 文字列の定義規則を思い出すと、ユーザーの入力が ASCII 文字列の場合、それを再コード化することで得られる結果がそれ自体であることがわかります。つまり、title_unicode_string の値が ASCII 文字列の場合、real_title_string と title_unicode_string の値はまったく同じになります。 ASCII 文字列は UTF-8 文字列でもあり、GTK2 システムに問題なく渡すことができます。

上記の例は Linux 上の PyGTK2 に関するものですが、同様の問題は PyGTK だけで発生するわけではありません。 PyGTK に加えて、PyQT、Tkinter など、現在のさまざまな Python バインド グラフィック パッケージでは、多かれ少なかれ Unicode 処理に関連する問題が発生します。

これで、Python の Unicode 文字列エンコード メカニズムがわかりましたが、最も知りたい疑問はまだ未解決です。Unicode を使用して中国語を処理する Python サポートをどのように作成できるでしょうか?この問題については次のセクションで説明します。

セクション 3: Python の Unicode 文字列を中国語にサポートさせる方法

このセクションのタイトルを読んだ後、Python の同僚の中には少し不満を抱く人もいるかもしれません:「なぜ中国語を処理するのに Unicode を使用しなければならないのですか? 私たちは通常、伝統的な Is を使用します。」 t Python 文字列の処理は良好ですか? 「確かに、一般に、文字列の連結や部分文字列の一致などの操作には、従来の Python 文字列で十分です。ただし、複数の言語を含む正規表現マッチング、テキスト編集、式分析などの高度な文字列操作が含まれる場合、これらの操作では、多数のシングルバイト テキストとマルチバイト テキストが混在します。従来の文字列処理は非常に面倒です。さらに、従来の文字列では、いまいましい「ハーフワード」問題を解決することはできません。 Unicode を使用できれば、これらの問題は簡単に解決できます。したがって、私たちは中国の Unicode 処理の問題に直面し、解決するよう努めなければなりません。

前のセクションの紹介から、Python の Unicode メカニズムを使用して文字列を処理したい場合は、マルチバイト中国語エンコード (GB エンコード シリーズおよび BIG5 シリーズを含む) と Unicode の間の双方向変換のみが必要であることがわかりました。エンコード/デコードモジュールがその役割を果たします。 Python の用語によれば、このようなエンコード/デコード モジュールはコーデックと呼ばれます。そこで次の疑問は、そのようなコーデックをどのように記述するかということです。

Python の Unicode メカニズムが Python コアにハードコーディングされている場合、Python に新しいコーデックを追加するのは困難な作業になります。幸いなことに、Python の設計者はそれほど愚かではありません。彼らは、Python に新しいコーデックを簡単に追加できる非常に拡張性の高いメカニズムを提供します。

Python の Unicode 処理モジュールには 3 つの最も重要なコンポーネントがあります。1 つは codecs.py ファイル、もう 1 つはエンコーディング ディレクトリ、そして 3 つ目は aliases.py ファイルです。最初の 2 つは、Python システム ライブラリのインストール ディレクトリにあります (Win32 ディストリビューションの場合は $PYTHON_HOME/lib/ ディレクトリにあり、Red Hat Linux の場合は /usr/lib/python にあります)。 -version/ ディレクトリー。他のシステムでも同様に見つけることができます)、最後のものはエンコーディング ディレクトリーにあります。次に、この3つをそれぞれ説明していきます。

まず codecs.py ファイルを見てみましょう。このファイルは、標準のコーデック モジュールが持つ必要があるインターフェイスを定義します。特定のコンテンツは独自の Python ディストリビューションにあるため、ここでは詳しく説明しません。 codecs.py ファイルの定義によれば、完全なコーデックには少なくとも 3 つのクラスと 1 つの標準関数が必要です:

1. コーデック クラス

目的:

は渡されたバッファ データを転送するために使用されます。ユーザー (バッファー) によって従来の Python 文字列として変換され、対応する Unicode 文字列に「デコード」されます。完全な Codec クラス定義では、Codec.decode() と

Codec.encode() の 2 つのメソッドを提供する必要があります。

Codec.decode(input, <a href="//m.sbmmt.com / wiki/222.html" target="_blank">errors</p> = "strict")

Codec.decode(input, <a href="//m.sbmmt.com/wiki/222.html" target="_blank">errors</a> = "strict")

用于将输入的数据看做是传统Python字符串,并将其“解码”,转换成对应的Unicode字符串。

参数:

input:输入的buffer(可以是字符串,也可以是任何可以转换成字符串表示的对象)

errors:发生转换错误时的处理选择。可选择如下三种取值:

strict(默认值):如果发生错误,则抛出UnicodeError异常;

replace:如果发生错误,则选取一个默认的Unicode编码代替之;

ignore:如果发生错误,则忽略这个字符,并继续分析余下的字符。

返回值:

一个常数列表(tuple):首元素为转换后的Unicode字符串,尾元素为输入数据的长度。

Codec.encode(input, errors = "strict") は、入力データを従来の Python 文字列として扱い、対応する Unicode 文字列に「デコード」するために使用されます。

パラメータ:

input: 入力バッファ (文字列、または文字列表現に変換できる任意のオブジェクトにすることができます)

errors: 変換エラーが発生した場合の処理​​オプション。次の 3 つの値から選択できます。

strict (デフォルト値): エラーが発生した場合、UnicodeError 例外がスローされます。

replace: エラーが発生した場合、代わりにデフォルトの Unicode エンコーディングが選択されます。エラーが発生した場合は、この文字を無視して残りの文字の分析を続けます。

戻り値:

定数リスト (タプル): 最初の要素は変換された Unicode 文字列で、最後の要素は入力データの長さです。 Codec.encode(input,errors = "strict") は、入力データを Unicode 文字列として扱い、対応する従来の Python 文字列に「エンコード」するために使用されます。 パラメータ:

🎜input: 入力バッファ(通常はUnicode文字列) 🎜🎜errors: 変換エラーが発生した場合の処理​​オプション。値の規則は Codec.decode() メソッドと同じです。 🎜🎜戻り値: 🎜🎜定数リスト (タプル): 最初の要素は変換された従来の Python 文字列で、最後の要素は入力データの長さです。 🎜🎜🎜🎜2. StreamReader クラス (通常は Codec クラスから🎜継承🎜する必要があります)🎜🎜🎜

用于分析文件输入流。提供所有对文件对象的读取操作,如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哈希表中就有一项表示其对应关系:

&#39;utf-8&#39; : &#39;utf_8&#39;, # the <a href="//m.sbmmt.com/code/8212.html" target="_blank">module</a> `utf_8&#39; is the codec <a href="//m.sbmmt.com/wiki/125.html" target="_blank">for</a> UTF-8

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

&#39;mycharset&#39; : &#39;mycharset.mycodec&#39;,

这里不必写出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和香港扩展版本)。虽然同一派系的编码可以向下兼容,但考虑到其字符数目庞大,为了加快查找速度,笔者个人认为还是将它们分开编码比较合理。当然,如果能够找到对应字符集的转换公式,则这种分离就没有必要了;

以上がUnicodeとPythonの中国語処理方法を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!