ASCII ではない utf-8でエンコードされたデータを含む文字列変数を作成することから始めます。
>>> text = 'á'
>>> text
'\xc3\xa1'
>>> text.decode('utf-8')
u'\xe1'
その上で使用unicode()
するとエラーが発生します...
>>> unicode(text)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0:
ordinal not in range(128)
...しかし、エンコーディングがわかっている場合は、それを2番目のパラメーターとして使用できます:
>>> unicode(text, 'utf-8')
u'\xe1'
>>> unicode(text, 'utf-8') == text.decode('utf-8')
True
__str__()
メソッドでこのテキストを返すクラスがあるとします。
>>> class ReturnsEncoded(object):
... def __str__(self):
... return text
...
>>> r = ReturnsEncoded()
>>> str(r)
'\xc3\xa1'
unicode(r)
上記str()
と同じエラーが発生するため、使用しているようです。unicode(text)
>>> unicode(r)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0:
ordinal not in range(128)
これまでのところ、すべてが計画どおりです!
しかし、誰も予想していなかったように、unicode(r, 'utf-8')
試してさえいません:
>>> unicode(r, 'utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, ReturnsEncoded found
なんで?この一貫性のない動作はなぜですか? バグですか?それは意図されていますか?非常に厄介です。