Unicode と Python についてはたくさんの説明があると思いますが、理解しやすく使いやすくするために、それらについてさらにいくつか書いていくつもりです。
まずはPythonで文字列を定義しましょう。文字列型を使用すると、実際にはバイト文字列が保存されます。
りーこの例では、文字列 abc はバイト文字列です。 97.、98、99 は ASCII コードです。 Python 2.x の定義では、すべての文字列を ASCII として扱います。残念ながら、ASCII はラテン文字セットの中で最も一般的ではない標準です。
ASCII は、文字マッピングに最初の 127 の数字を使用します。 Windows-1252 や UTF-8 などの文字マップは、最初の 127 文字が同じです。文字列内の各バイトの値が 127 未満の場合は、文字列エンコーディングを混合しても安全です。ただし、以下で説明するように、この仮定を行うことには危険があります。
文字列内に 126 を超える値のバイトがある場合、問題が発生します。 Windows-1252 でエンコードされた文字列を見てみましょう。 Windows-1252 の文字マッピングは 8 ビット文字マッピングであるため、合計 256 文字になります。最初の 127 文字は ASCII と同じで、次の 127 文字は Windows-1252 で定義された他の文字です。
りーWindows-1252 はまだバイト文字列ですが、最後のバイトの値が 126 より大きいことがわかりましたか? Python がデフォルトの ASCII 標準を使用してこのバイト ストリームをデコードしようとすると、エラーが報告されます。 Python がこの文字列をデコードすると何が起こるか見てみましょう:
1 2 |
|
UTF-8 を使用して別の文字列をエンコードしてみましょう:
1 2 |
|
よく知っている Unicode エンコーディング テーブルを選択すると、英語のダッシュに対応する Unicode コード ポイントが 8211 (0x2013) であることがわかります。この値は、ASCII の最大値 127 よりも大きくなります。 1バイト以上の値を格納できます。 8211 (0x2013) は 2 バイトであるため、UTF-8 はいくつかのトリックを使用して、1 文字を保存するのに 3 バイト必要であることをシステムに伝える必要があります。 Python がデフォルトの ASCII を使用して、文字値が 126 より大きい UTF-8 でエンコードされた文字列をエンコードする場合を見てみましょう。
りーご覧のとおり、Python はデフォルトで常に ASCII エンコーディングを使用してきました。 4 番目の文字を処理すると、その値が 226 で 126 より大きいため、Python はエラーをスローします。これは混合エンコーディングの問題です。
初めて Python Unicode を学習する場合、デコードという用語が混乱する可能性があります。バイト ストリームを Unicode オブジェクトにデコードしたり、Unicode オブジェクトをバイト ストリームにエンコードしたりできます。
Python は、バイト ストリームを Unicode オブジェクトにデコードする方法を知る必要があります。バイト ストリームを取得したら、その「decode」メソッドを呼び出して、そこから Unicode オブジェクトを作成します。 できるだけ早くバイト ストリームを Unicode にデコードすることをお勧めします。
りーUnicode をバイトストリームにエンコードします
コーデックモジュールの使用
これを試してください:
1 2 3 4 5 6 7 |
|
これは Unicode オブジェクトを取得し、それを UTF-8 エンコーディングでファイルに書き込みます。他の状況でも使用できます。
これを試してください:
ファイルからデータを読み取るとき、codecs.open は、UTF-8 でエンコードされたファイルを Unicode オブジェクトに自動的に変換できるファイル オブジェクトを作成します。
上の例を続けてみましょう。今回は urllib ストリームを使用します。
りー単行バージョン:
1 2 3 |
|
コーデック モジュールには細心の注意が必要です。渡すものは Unicode オブジェクトである必要があります。そうでない場合は、バイト ストリームが ASCII として自動的にデコードされます。
りーおっと、Python は再び ASCII を使用してすべてをデコードし始めました。
UTF-8バイトストリームのスライスの問題
次に、次の操作を行います:
1 2 3 4 5 6 7 |
|
何? 4 文字のように見えますが、len の結果では 6 文字になっています。 len は文字数ではなくバイト数をカウントするためです。
りーでは、この文字列を分割してみましょう。
りーセグメンテーションの結果は最後のバイトであり、最後の文字ではありません。
UTF-8 を正しくセグメント化するには、バイト ストリームをデコードして Unicode オブジェクトを作成することをお勧めします。そうすれば、安全に操作してカウントできます。
りーPython が自動的にエンコード/デコードする場合
第一个案例是当它试着将Unicode和字节串合并在一起的时候。
1 2 3 4 |
|
在合并列表的时候会发生同样的情况。Python在列表里有string和Unicode对象的时候会自动地将字节串解码为Unicode。
1 2 3 4 |
|
或者当试着格式化一个字节串的时候:
1 2 3 4 |
|
基本上当你把Unicode和字节串混在一起用的时候,就会导致出错。
在这个例子里面,你创建一个utf-8文件,然后往里面添加一些Unicode对象的文本。就会报UnicodeDecodeError错误。
1 2 3 4 5 6 7 8 9 10 11 |
|
你可以使用codecs模块把文件作为Unicode加载来解决这个问题。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
正如你看到的,由codecs.open 创建的流在当数据被读取的时候自动地将比特串转化为Unicode。
1.最先解码,最后编码
2.默认使用utf-8编码
3.使用codecs和Unicode对象来简化处理
最先解码意味着无论何时有字节流输入,需要尽早将输入解码为Unicode。这会防止出现len( )和切分utf-8字节流发生问题。
最后编码意味着只有在准备输入的时候才进行编码。这个输出可能是一个文件,一个数据库,一个socket等等。只有在处理完成之后才编码unicode对象。最后编码也意味着,不要让Python为你编码Unicode对象。Python将会使用ASCII编码,你的程序会崩溃。
默认使用UTF-8编码意味着:因为UTF-8可以处理任何Unicode字符,所以你最好用它来替代windows-1252和ASCII。
codecs模块能够让我们在处理诸如文件或socket这样的流的时候能少踩一些坑。如果没有codecs提供的这个工具,你就必须将文件内容读取为字节流,然后将这个字节流解码为Unicode对象。
codecs模块能够让你快速的将字节流转化为Unicode对象,省去很多麻烦。
最后的部分是让你能入门UTF-8,如果你是个超级极客可以无视这一段。
利用UTF-8,任何在127和255之间的字节是特别的。这些字节告诉系统这些字节是多字节序列的一部分。
1 2 |
|
最后3字节是一个UTF-8多字节序列。如果你把这三个字节里的第一个转化为2进制可以看到以下的结果:
1 |
|
前3比特告诉系统它开始了一个3字节序列226,128,147。
那么完整的字节序列。
1 |
|
然后你运用三字节序列的下面的掩码。
1 2 3 4 |
|
这是基本的UTF-8入门,如果想知道更多的细节,可以去看UTF-8的维基页面。
原文链接: ERIC MORITZ 翻译: 伯乐在线 - 贱圣OMG
以上がPython エンコーディングと Unicode について学ぶの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。