Pythonの文字列の話
エキスパートPythonプログラミング読書会19に参加して、Unicodeの話を聞いてきました。自分が理解できた範囲でメモしておきます。decode(), encode(), io.open()を使いこなせるようになれば、UnicodeErrorに困ることも減るのでは、と感じました。
文字列にはstr型 (バイト文字列) とunicode型 (ユニコード文字列) の2種類がある。
>>> type('こんにちは') <type 'str'> >>> type(u'こんにちは') <type 'unicode'>
str型の文字列は思い通りの文字列処理ができない。unicode型を使うべき。
>>> len('こんにちは') 15 >>> len(u'こんにちは') 5
str型→unicode型には、decode()を、unicode型→str型にはencode()を使う。
>>> u = 'こんにちは'.decode('utf-8') >>> type(u) <type 'unicode'> >>> s = u'こんにちは'.encode('utf-8') >>> type(s) <type 'str'>
decode()とencode()を間違えるとエラーになる。
>>> 'こんにちは'.encode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128) >>> u'こんにちは'.decode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)
unicode型の内部表現にはUTF-16とUTF-32がある。sys.maxunicodeが65536ならUTF-16、1114111ならUTF-32。
>>> import sys >>> sys.maxunicode 1114111
str型とunicode型の変換でデフォルトで使用されるエンコーディングはascii。
>>> import sys >>> sys.getdefaultencoding() 'ascii' >>> u = 'こんにちは'.decode() Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)
デフォルトエンコーディングを変更できるが、問題の原因を見つけにくくなるのでやらない。
>>> import sys >>> reload(sys) <module 'sys' (built-in)> >>> sys.setdefaultencoding('utf-8') >>> sys.getdefaultencoding() 'utf-8' >>> u = 'こんにちは'.decode() >>> type(u) <type 'unicode'>
io.open()を使うと、unicode型で読み書きできる。
>>> f = open('foo.txt') >>> line = f.readline() >>> type(line) <type 'str'> >>> import io >>> f = io.open('foo.txt') >>> line = f.readline() >>> type(line) <type 'unicode'>
Python3では文字列がunicode型にまとめられ、文字列処理が簡単になった。しかし、まだPython3に対応していないライブラリも多い。どのライブラリが対応しているかはPython 3 Support on PyPIから確認できる。