ホームページ >バックエンド開発 >Python チュートリアル >Python での中国語エンコードの問題について
この記事の内容は、Python での中国語のエンコーディングの問題に関するものであり、必要な友人と共有します
1。1.1 .py ファイルのエンコード Python のデフォルトのスクリプト ファイルはすべて ANSCII エンコードされています。ファイル内に ANSCII エンコード範囲にない文字がある場合は、「エンコード命令」を使用して修正する必要があります。 モジュールの定義で、.py ファイルに中国語の文字が含まれている場合 (厳密に言えば、ANSCII 以外の文字が含まれている場合)、1 行目または 2 行目にエンコーディング ステートメントを指定する必要があります:
# -*-coding=utf -8 -*-or #coding=utf-8 gbk、gb2312 などの他のエンコーディングも使用できます。そうでない場合は、次のようなメッセージが表示されます。 SyntaxError: Non-ASCII Character '/xe4' in file ChineseTest.py on line 1,ただし、エンコーディングが宣言されていません。例外情報の詳細については、http://www.pytho を参照してください。
1.2 Python でのエンコーディングとデコーディングまず、 Python には str と unicode という 2 つの文字列型があり、どちらも Basestring の派生クラスであり、 str 型は Unicode の各単位を表す文字列です。つまり、
len(u'China') の値は 2; len('ab') の値も 2 です str ドキュメントには次のような文があります。たとえば、ファイルから読み取られたデータを保持する場合、ファイルのコンテンツを読み取るとき、またはネットワークからコンテンツを読み取るとき、保持されるオブジェクトは str 型に変換されます。特定のエンコーディング タイプの場合は、str を Unicode に変換してから、Unicode から utf-8、gb2312 などの特定のエンコーディング タイプに変換する必要があります。
Python で提供される変換関数:
unicode から gb2312、utf- 8など
# -*- coding=UTF-8 -*- if __name__ == '__main__': s = u'中国' s_gb = s.encode('gb2312')
utf-8、GBKは関数unicode(s,encoding)またはs.decode(encoding)を使用してunicodeに変換されます
# -*- coding=UTF-8 -*- if __name__ == '__main__': s = u'中国' #s为unicode先转为utf-8 s_utf8 = s.encode('UTF-8') assert(s_utf8.decode('utf-8') == s)
通常のstrはunicodeに変換されます
# -*- coding=UTF-8 -*- if __name__ == '__main__': s = '中国' su = u'中国'' #s为unicode先转为utf-8 #因为s为所在的.py(# -*- coding=UTF-8 -*-)编码为utf-8 s_unicode = s.decode('UTF-8') assert(s_unicode == su) #s转为gb2312,先转为unicode再转为gb2312 s.decode('utf-8').encode('gb2312') #如果直接执行s.encode('gb2312')会发生什么? s.encode('gb2312') # -*- coding=UTF-8 -*- if __name__ == '__main__': s = '中国' #如果直接执行s.encode('gb2312')会发生什么? s.encode('gb2312')
例外が発生しますここ:
Python は、まず s を Unicode にデコードし、次に gb2312 にエンコードします。デコードは Python によって自動的に実行され、デコード方法を指定しないため、Python は sys.defaultencoding で指定された方法を使用してデコードします。多くの場合、sys.defaultencoding は ANSCII であり、s がこのタイプでない場合はエラーが発生します。
上記の状況を例として、sys.defaultencoding が ancii であり、s のエンコード方式がファイルのエンコード方式 (utf8) と同じであるため、エラーが発生しました: UnicodeDecodeError: 'ascii' codec can' t 位置 0 のバイト 0xe4 をデコードします: 序数が範囲 (128) にありませんこの場合、エラーを修正するには 2 つの方法があります:
1 つは s のエンコード方式を明確に示すことです#! /usr/bin/env python # -*- coding: utf-8 -*- s = '中文' s.decode('utf-8').encode('gb2312')
もう 1 つは sys を変更することです.defaultencoding をファイルのエンコード方式にします
#! /usr/bin/env python # -*- coding: utf-8 -*- import sys reload(sys) # Python2.5 初始化后会删除 sys.setdefaultencoding 这个方法,我们需要重新载入 sys.setdefaultencoding('utf-8') str = '中文' str.encode('gb2312')
ファイルのエンコードと印刷関数
abc 中国語
読むには Python を使用します #coding=gbkprint open("Test .txt").read()結果: abc 中国語
ファイル形式を UTF-8 に変更します:
結果: abc涓枃
明らかに、ここではデコードが必要です:
# coding=gbk import codecs print open("Test.txt").read().decode("utf-8")
Traceback (most recent call last): File "ChineseTest.py", line 3, in <module> print open("Test.txt").read().decode("utf-8") UnicodeEncodeError: 'gbk' codec can't encode character u'/ufeff' in position 0: illegal multibyte sequenceメモ帳などの一部のソフトウェアでは、ファイルを保存するときに UTF-8 でエンコードすると、ファイルの先頭に 3 つの不可視文字 (0xEF 0xBB 0xBF、または BOM) が挿入されることがわかりました。
したがって、読み取るときにこれらの文字を自分で削除する必要があります。Python のコーデック モジュールは次の定数を定義します:
# coding=gbk import codecs data = open("Test.txt").read() if data[:3] == codecs.BOM_UTF8: data = data[3:] print data.decode("utf-8")
(4) いくつかの残りの問題
2 番目の部分では、Unicode を使用します。 str を Unicode に変換する関数と decode メソッド。これら 2 つの関数のパラメーターに「gbk」が使用されるのはなぜですか?
最初の反応は、コーディング ステートメントで gbk (#coding=gbk) を使用しているということですが、これは本当にそうなのでしょうか?
# coding=utf-8
s = "中文"
print unicode(s, "utf-8")
実行、エラーメッセージ:
Traceback (most recent call last): File "ChineseTest.py", line 3, in <module> s = unicode(s, "utf-8") UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: invalid data
# coding=utf-8 s = "中文" print unicode(s, "gbk")
Python での print の原理:
Python が print ステートメントを実行すると、単に出力をオペレーティング システムに渡します (fwrite( を使用) ) など)、実際にその出力を画面に表示するのは他のプログラムです。たとえば、Windows では、結果を表示するのは Windows コンソール サブシステムである可能性があります。また、Windows を使用していて Python を実行している場合も同様です。他の場所の Unix ボックスでは、実際にデータを表示するのは Windows SSH クライアントです。Unix 上の xterm で Python を実行している場合、xterm と X サーバーが表示を処理します。
To print data reliably, you must know the encoding that this display program expects.
简单地说,python中的print直接把字符串传递给操作系统,所以你需要把str解码成与操作系统一致的格式。Windows使用CP936(几乎与gbk相同),所以这里可以使用gbk。
最后测试:
# coding=utf-8 s = "中文" rint unicode(s, "cp936") # 结果:中文
这也可以解释为何如下输出不一致:
>>> s="哈哈" >>> s' \xe5\x93\x88\xe5\x93\x88' >>> print s #这里为啥就可以呢? 见上文对print的解释 哈哈>>> import sys >>> sys.getdefaultencoding() ' ascii' >>> print s.encode('utf8') # s在encode之前系统默认按ascii模式把s解码为unicode,然后再encode为utf8 Traceback (most recent call last): File "<stdin>", line 1, in ? UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128) >>> print s.decode('utf-8').encode('utf8') 哈哈 >>>
编码问题测试
使用 chardet 可以很方便的实现字符串/文件的编码检测
例子如下:
>>> import urllib>>> rawdata = urllib.urlopen('http://www.google.cn/').read()>>> import chardet >>> chardet.detect(rawdata){'confidence': 0.98999999999999999, 'encoding': 'GB2312'}>>>
chardet 下载地址 http://chardet.feedparser.org/
特别提示:
在工作中,经常遇到,读取一个文件,或者是从网页获取一个问题,明明看着是gb2312的编码,可是当使用decode转时,总是出错,这个时候,可以使用decode('gb18030')这个字符集来解决,如果还是有问题,这个时候,一定要注意,decode还有一个参数,比如,若要将某个String对象s从gbk内码转换为UTF-8,可以如下操作
s.decode('gbk').encode('utf-8′)
可是,在实际开发中,我发现,这种办法经常会出现异常:
UnicodeDecodeError: ‘gbk' codec can't decode bytes in position 30664-30665: illegal multibyte sequence
这 是因为遇到了非法字符——尤其是在某些用C/C++编写的程序中,全角空格往往有多种不同的实现方式,比如/xa3/xa0,或者/xa4/x57,这些 字符,看起来都是全角空格,但它们并不是“合法”的全角空格(真正的全角空格是/xa1/xa1),因此在转码的过程中出现了异常。
这样的问题很让人头疼,因为只要字符串中出现了一个非法字符,整个字符串——有时候,就是整篇文章——就都无法转码。
解决办法:
s.decode('gbk', ‘ignore').encode('utf-8′)
因为decode的函数原型是decode([encoding], [errors='strict']),可以用第二个参数控制错误处理的策略,默认的参数就是strict,代表遇到非法字符时抛出异常;
如果设置为ignore,则会忽略非法字符;
如果设置为replace,则会用?取代非法字符;
如果设置为xmlcharrefreplace,则使用XML的字符引用。
python文档
decode( [encoding[, errors]])
Decodes the string using the codec registered for encoding. encoding defaults to the default string encoding. errors may be given to set a different error handling scheme. The default is 'strict', meaning that encoding errors raise UnicodeError. Other possible values are 'ignore', 'replace' and any other name registered via codecs.register_error, see section 4.8.1.
详细出处参考:http://www.jb51.net/article/16104.htm
参考文献
【1】Python编码转换
【3】Python编码实现
以上がPython での中国語エンコードの問題についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。