ホームページ  >  記事  >  バックエンド開発  >  Python での中国語エンコードの問題について

Python での中国語エンコードの問題について

零到壹度
零到壹度オリジナル
2018-04-16 11:38:501548ブラウズ

この記事の内容は、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')


ファイルのエンコードと印刷関数

ファイル test.txt を作成します。ファイル形式は ANSI、内容は次のとおりです:

abc 中国語

読むには Python を使用します

#coding=gbkprint open("Test .txt").read()結果: abc 中国語
ファイル形式を UTF-8 に変更します:
結果: abc涓枃
明らかに、ここではデコードが必要です:

# coding=gbk
import codecs
print open("Test.txt").read().decode("utf-8")

結果: abc Chinese
上記のテストは Editplus を使用して編集しましたが、Windows に付属のメモ帳を使用して編集して UTF-8 形式で保存すると、
実行時にエラーが発生しました:

Traceback (most recent call last):
  File "ChineseTest.py", line 3, in <module>
    print open("Test.txt").read().decode("utf-8")
UnicodeEncodeError: &#39;gbk&#39; codec can&#39;t encode character u&#39;/ufeff&#39; 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")

結果: abc 中国語



(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: &#39;utf8&#39; codec can&#39;t decode bytes in position 0-1: invalid data

明らかに、gbk が両側で使用されているため前のものが正常である場合、ここでは両側で utf-8 の一貫性を維持します。正常であるはずで、エラーは報告されません。
さらなる例として、ここでまだ変換に gbk を使用する場合:

# 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&#39;
\xe5\x93\x88\xe5\x93\x88&#39;
>>> print s  #这里为啥就可以呢? 见上文对print的解释
哈哈>>> import sys
>>> sys.getdefaultencoding() &#39;
ascii&#39;
>>> print s.encode(&#39;utf8&#39;)  # s在encode之前系统默认按ascii模式把s解码为unicode,然后再encode为utf8
Traceback (most recent call last):
File "<stdin>", line 1, in ?
UnicodeDecodeError: &#39;ascii&#39; codec can&#39;t decode byte 0xe5 in position 0: ordinal not in range(128)
>>> print s.decode(&#39;utf-8&#39;).encode(&#39;utf8&#39;)
哈哈
>>>

编码问题测试

使用 chardet 可以很方便的实现字符串/文件的编码检测

例子如下:

>>>
 import
 urllib>>>
 rawdata = urllib.urlopen(&#39;http://www.google.cn/&#39;).read()>>>
 import
 chardet
>>>
 chardet.detect(rawdata){&#39;confidence&#39;: 0.98999999999999999, &#39;encoding&#39;: &#39;GB2312&#39;}>>>

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(&#39;gbk&#39;, ‘ignore&#39;).encode(&#39;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编码转换

【2】全角半角转换的Python实现

【3】Python编码实现

以上がPython での中国語エンコードの問題についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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