pythonで仕事してるとちょいちょいUnicodeEncodeErrorとかUnicodeDecodeErrorに遭遇します。
最初ははまると思うんで原因と対応方法についてメモしておきます。
python2系の話です。
まずstr型とunicode型の違い
pythonのstrはバイト文字列、unicodeはユニコード文字列です
# coding=utf-8 s = "あ" print [s] # => ['\xe3\x81\x82'] u = u"あ" print [u] # => [u'\u3042']
len関数は、str型に対して使うとバイト数を返すので文字数のカウントには使えません
unicode型に対して使うと文字数が返されます
print len(s) # => 3 print len(u) # => 1
str型をunicode型に変換するのにdecode関数を使います
ファイルの冒頭でcoding=utf-8を渡しているので、str型のsはutf-8のバイトを保持してます。
そのためdecodeにutf-8を渡してます。
decoded_s = s.decode('utf-8') print type(decoded_s) # => <type 'unicode'> print [decoded_s] # => [u'\u3042']
sjisなどでdecodeしようとするとエラーになります
try: s.decode('sjis') except UnicodeDecodeError, e: print e # => 'shift_jis' codec can't decode byte 0x82 in position 2: incomplete multibyte sequence
ファイルを読み込んで処理する場合など、どのような文字コードが保持されているかわからない場合は注意が必要です
f = open('/path/to/sjis.txt', 'r') sjis_content = f.read() print type(sjis_content) # => <type 'str'> decoded_content = sjis_content.decode('sjis') print decoded_content # => あ
unicode型をstr型に変換する場合はencodeを使います
encoded_u = u.encode('utf-8') print type(encoded_u) # => <type 'str'> print [encoded_u] # => ['\xe3\x81\x82']
指定された文字コードに変換出来ない場合、UnicodeEncodeErrorが発生します
以下の場合、①がShift_JISにないのでエラーになってます
u2 = u"\u2460" print [u2] # => [u'\u2460'] try: u2.encode('sjis') except UnicodeEncodeError, e: print e # => 'shift_jis' codec can't encode character u'\u2460' in position 0: illegal multibyte sequence
sjis-2004やutf-8にならencodeすることができます
u2_encoded = u2.encode('sjis-2004') print type(u2_encoded) print [u2_encoded] # => <type 'str'> # => ['\x87@'] u2_encoded = u2.encode('utf-8') print type(u2_encoded) print [u2_encoded] # => <type 'str'> # => ['\xe2\x91\xa0']