Я начинаю с создания строковой переменной с некоторыми не-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)
... но если я знаю кодировку, я могу использовать ее в качестве второго параметра:
>>> 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
Почему? Почему это противоречивое поведение? Это ошибка? это предназначено? Очень неловко.