Ответ 1
У вас есть 3 или 4 или 5 проблемы... но repr()
и unicodedata.name()
- ваши друзья; они однозначно показывают вам, что у вас есть, без путаницы, порожденной людьми с разными консольными кодировками, сообщающими результаты print fubar
.
Сводка: либо (а) вы начинаете с объекта unicode и применяете к нему функцию unquote, либо (b) вы начинаете с объекта str, а ваша консольная кодировка - не UTF-8.
Если вы говорите, что начинаете с объекта unicode:
>>> s0 = u'%C3%A7%C3%B6asd+fjkls%25asd'
>>> print repr(s0)
u'%C3%A7%C3%B6asd+fjkls%25asd'
Это случайная чепуха. Если вы примените к нему urllibX.unquote_YYYY()
, вы получите еще один бессмысленный unicode-объект (u'\xc3\xa7\xc3\xb6asd+fjkls%asd'
), который вызовет проявленные вами симптомы при печати. Вы должны немедленно конвертировать исходный объект unicode в объект str:
>>> s1 = s0.encode('ascii')
>>> print repr(s1)
'%C3%A7%C3%B6asd+fjkls%25asd'
то вы должны его недооценить:
>>> import urllib2
>>> s2 = urllib2.unquote(s1)
>>> print repr(s2)
'\xc3\xa7\xc3\xb6asd+fjkls%asd'
Рассматривая первые 4 байта, он кодируется в UTF-8. Если вы сделаете print s2
, он будет выглядеть нормально, если ваша консоль ожидает UTF-8, но если он ожидает ISO-8859-1 (aka latin1), вы увидите свой симптомный мусор (первый char будет A-тильдой). Пусть парк, который задумался и превратит его в объект Unicode:
>>> s3 = s2.decode('utf8')
>>> print repr(s3)
u'\xe7\xf6asd+fjkls%asd'
и осмотрите его, чтобы узнать, что у нас есть:
>>> import unicodedata
>>> for c in s3[:6]:
... print repr(c), unicodedata.name(c)
...
u'\xe7' LATIN SMALL LETTER C WITH CEDILLA
u'\xf6' LATIN SMALL LETTER O WITH DIAERESIS
u'a' LATIN SMALL LETTER A
u's' LATIN SMALL LETTER S
u'd' LATIN SMALL LETTER D
u'+' PLUS SIGN
Похоже, вы сказали, что ожидаете. Теперь мы переходим к вопросу о его отображении на консоли. Примечание: не волнуйтесь, когда вы видите "cp850"; Я делаю это переносимо и просто выполняю это в командной строке в Windows.
>>> import sys
>>> sys.stdout.encoding
'cp850'
>>> print s3
çöasd+fjkls%asd
Примечание. Объект unicode был явно закодирован с использованием sys.stdout.encoding. К счастью, все символы юникода в s3
могут быть представлены в этой кодировке (и cp1252 и latin1).