ホームページ  >  記事  >  バックエンド開発  >  Pythonの中国語文字化け問題を徹底分析

Pythonの中国語文字化け問題を徹底分析

高洛峰
高洛峰オリジナル
2017-01-13 16:07:131058ブラウズ

この記事では、「Ha」を例としてすべての問題を説明します。「Ha」のさまざまなエンコーディングは次のとおりです。
1. UNICODE (UTF8-16)、
2。 UTF-8、E59388; 3. GBK、B9FE。
1. Python の str と unicode
長い間、Python の中国語エンコーディングは非常に大きな問題であり、エンコーディング変換例外が頻繁にスローされます。Python の str と unicode とは何ですか?
Python で Unicode という場合、通常は Unicode オブジェクトを指します。たとえば、「haha」の Unicode オブジェクトは
u'u54c8u54c8' です。
このバイト配列は Unicode オブジェクトのエンコーディングを表します。 utf-8、gbk、cp936、GB2312 以降のストレージ形式を使用できます。ここでは、これは単なるバイト ストリームであり、他の意味はありません。このバイト ストリームによって表示されるコンテンツを意味のあるものにしたい場合は、正しいエンコード形式を使用してデコードし、表示する必要があります。
例:

python 中文乱码问题深入分析

Unicode オブジェクトを utf-8 でエンコードされた str-s_utf8 にエンコードします。s_utf8 はバイト配列で、ストレージは 'xe5x93x88xe5x93x88' ですが、出力したい場合、これは単なるバイト配列です。印刷ステートメントを通してそれを笑った場合、あなたはがっかりするでしょう、なぜですか?

print ステートメントの実装は出力コンテンツをオペレーティング システムに送信することであるため、オペレーティング システムはシステムのエンコーディングに従って入力バイト ストリームをエンコードします。これが、UTF-8 形式の文字列「haha」を出力する理由の説明になります。 「xe5x93x88xe5x93x88」は GB2312 によって解釈され、「鍝鍚搱」と表示されるため、「鍝獚搱」です。もう一度強調しておきますが、str はバイト配列を記録しますが、これは特定のエンコード記憶形式にすぎません。ファイルへの出力または印刷出力の形式は、デコード エンコードによってどのようにデコードされるかに完全に依存します。

ここで print について少し追加説明します: Unicode オブジェクトが print に渡されると、Unicode オブジェクトは内部でローカルのデフォルトのエンコーディングに変換されます (これは単なる個人的な推測です)

2. str str と unicode の変換オブジェクト

str オブジェクトと Unicode オブジェクトの変換は、エンコードとデコードによって行われます。具体的な使用方法は次のとおりです:

python 中文乱码问题深入分析

GBK 'haha' を Unicode に変換し、それから UTF8 に変換します

3 つ、Setdefaultencoding

python 中文乱码问题深入分析

上記のデモ コードに示すように:


s (gbk 文字列) が utf-8 に直接エンコードされる場合、例外がスローされますが、次のコードを呼び出すことで:

import sys

reload( sys)

sys.setdefaultencoding('gbk')

変換は成功する可能性があります。なぜですか? Python での str と unicode のエンコードとデコードのプロセスでは、str が別のエンコードに直接エンコードされると、str が最初に unicode にデコードされ、使用されるエンコードがデフォルトのエンコードになります。通常、デフォルトのエンコードは ancii です。上記の例では、コードの最初の変換中にエラーが発生します。現在のデフォルトのエンコーディングを「gbk」に設定すると、エラーは発生しません。

reload(sys)については、Python2.5では初期化後にsys.setdefaultencodingメソッドが削除されるため、リロードする必要があります。

4. さまざまなエンコード形式でファイルを操作する

ファイル形式は ANSI で、内容は次のとおりです:


abc Chinese

読み取りには Python を使用します

#coding=gbk

print open ("Test.txt").read()

結果: abc 中国語

ファイル形式を UTF-8 に変更します:

結果: abc涓枃

明らかに、ここではデコードが必要です:

#coding= gbk

import codecs

print open("Test.txt").read().decode("utf-8")

結果: abc Chinese

上記の test.txt を編集するために Editplus を使用しました。 Windows に付属のメモ帳を使用して編集し、UTF-8 形式で保存します。

実行時にエラー メッセージが表示されます:

トレースバック (最新の呼び出しは最後):

ファイル " ChineseTest.py"、行 3、

で print open("Test.txt").read().decode("utf-8")

UnicodeEncodeError: 'gbk' コーデックは位置 0 で文字 u'ufeff' をエンコードできません: 不正なマルチバイト シーケンス

メモ帳などの一部のソフトウェアでは、UTF-8 でエンコードされたファイルを保存すると、最終的にファイルの先頭に 3 つの非表示文字 (0xEF 0xBB 0xBF、BOM) を挿入します。

そのため、読み取り時にこれらの文字を自分で削除する必要があります。Python の codecs モジュールは次の定数を定義します:

#coding=gbk

import codecs

data = open("Test.txt").read()

if data[:3] == codecs.BOM_UTF8:

data = data[3:]

print data.decode("utf-8")

結果: abc Chinese

5. ファイルエンコード形式と役割エンコーディング宣言の

ソースファイルのエンコーディング形式は文字列の宣言にどのような影響を与えますか?この問題は長い間私を悩ませてきましたが、今ようやくいくつかの手がかりが得られました。ファイルのエンコード形式によって、ソース ファイルで宣言された文字列のエンコード形式が決まります。たとえば、次のようになります。 print repr(str)

a. ファイル形式が utf-8 の場合、str の値は次のとおりです: 'xe5x93x88xe5x93x88' (haha の utf-8 エンコーディング)

b. ファイル形式が gbk の場合、str の値は次のようになります。 : 'xb9xfexb9xfe' (笑 gbkエンコード)

最初のセクションでも述べたように、Pythonの文字列は単なるバイト配列であるため、aの場合のstrをgbkエンコードコンソールに出力すると文字化けして表示されます。 :鍝埚搱; そして、ケースbのstrをutf-8エンコードされたコンソールに出力すると、文字化けの問題も表示され、おそらくutf-8デコードを使用して「xb9xfexb9xfe」が表示されます。そして空白になります。 >_<

ファイル形式について説明した後、各ファイルの先頭で #coding=gbk のようなステートメントを使用してエンコーディングを宣言します。この文の?これまでのところ、これには 3 つの機能があると思います:

非 ASCII エンコーディングがソース ファイル (通常は中国語) に表示されることを示します。

高度な IDE では、IDE は指定したエンコーディング形式でファイル形式を保存します。

ソースコード内の u'ha' のような宣言で 'ha' を Unicode にデコードするために使用されるエンコード形式の決定も、混乱を招く場所です。例を参照してください:

#coding:gbk


ss = u'。 haha'


print repr(ss)

print 'ss:%s' % ss

これらのコードを utf-8 テキストに保存して実行すると、何が出力されると思いますか?誰もが出力は次のようになったはずです:

u'u54c8u54c8'

ss: はは

しかし、実際の出力は:

u'u935du581du6431'

ss:埚搱

なぜこれが起こっているのでしょうか? ss = u'haha' を実行する場合、プロセス全体は次のステップに分割できます:

1) 'haha' のエンコーディングを取得します。ファイルのエンコーディング形式によって決まります。は 'xe5x93x88xe5x93x88' (母の utf-8 エンコード形式) です

2) Unicode エンコードに変換するとき、この変換プロセス中に、「xe5x93x88xe5x93x88」のデコードは utf-8 ではなく、宣言で指定されたエンコード GBK でデコードされます。エンコードし、GBK に従って 'xe5x93x88xe5x93x88' をデコードし、 '鍝韚搱' を取得します。これらの 3 文字の Unicode エンコードは u'u935du581du6431' であり、これが print repr(ss) が u'u935du581du6431' を出力する理由の説明になります。

わかりました、これは少しわかりにくいので、次の例を分析してみましょう:

#-*-coding:utf-8 -*-

ss = u'haha'

print repr(ss)

print 'ss :%s' % ss

今回はこの例を GBK エンコードに保存します。実行結果は次のようになります。

UnicodeDecodeError: 'utf8' コーデックは位置 0 のバイト 0xb9 をデコードできません: 予期しないコード バイト

なぜここにあるのでしょうか? utf8デコードエラーはありますか?前の例を考えると、変換の最初のステップでは、ファイルのエンコーディングが GBK であるため、変換時に得られるエンコーディングは「haha」になります。これは、GBK エンコーディングの「xb9xfexb9xfe」です。 Unicode に変換するには、UTF8 が使用されます。「xb9xfexb9xfe」をデコードし、utf-8 エンコード テーブルを確認すると、utf8 エンコード テーブルにまったく存在しないことがわかります (UTF-8 の説明については、を参照してください)。文字エンコーディングに注意してください: ASCII、UTF-8、UNICODE)、上記のエラーが報告されます。

Python の中国語文字化け問題の詳細な分析と関連記事については、PHP 中国語 Web サイトに注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。