Pythonのバイト文字列とユニコード文字列のお話
はじめに
Pythonは非常に気持ちいい言語である。しかしunicodeを扱おうと思ったとたん、イライラさせられる。日本人のプログラマーはRubyを使っている人が多いけど、このあたりの違いによる物なのかなぁ〜と勝手に思ってみたり、、、さて本題
マルチバイト文字について
str型は1文字=1バイトのバイト列として文字列を扱う。しかし日本語の場合1バイトでは全ての文字を表現しきれないので、1文字に対して複数バイトを割り当てるマルチバイトコーディングが利用されている。MS-DOSでは、デフォルトでshift-JISが使われている。shift-JISは2バイト目に\が使われる場合がある。具体的には漢字の’表’カタカナの’ソ’がこれにあたる。\はWindowsでパスの区切りなどに使われており、誤認されることがある。
つまり、ファイルパス(フォルダ名やファイル名)に表やソが混じっていると予期せぬところでパスが区切られてしまう。
>>> s = '表a\\ソ連.txt'
>>> s
'\x95\\a\\\x83\\\x98A.txt'
>>> s.split(os.path.sep)
['\x95', 'a', '\x83', '\x98A.txt']
Unicodeにまつわるエラー
unicode型とstr型の操作はunicodeに自動変換されて行われる。したがってASCIIがカバーしている範囲(英数字)であれば比較や、演算も問題ない。
>>> 'abc' == u'abc'
True
>>> 'abc' + u'abc'
u'abcabc'
問題を起こすのは下記の様に、unicode型と日本語が入っているstr型を比較したときである。
このエラーは日本語が入っているstr型'あ'をASCIIコードでデコードしてunicode型に変換しようとしたらASCIIコードの範囲外(ASCIIコードは0x00から0x7fまで)の0x82が出てきて変換できませんと怒られている。
>>> u'abc' + 'あ'
Traceback (most recent call last):
File "", line 1, in
UnicodeDecodeError: 'ascii' codec can't decode byte 0x82 in position 0: ordinal
not in range(128)