Как преобразовать Unicode в строку на уровне Python?

Следующий unicode и строка могут существовать самостоятельно, если они определены явно:

>>> value_str='Andr\xc3\xa9'
>>> value_uni=u'Andr\xc3\xa9'

Если у меня есть только u'Andr\xc3\xa9', назначенный переменной, как указано выше, как мне преобразовать ее в 'Andr\xc3\xa9' в Python 2.5 или 2.6?

EDIT:

Я сделал следующее:

>>> value_uni.encode('latin-1')
'Andr\xc3\xa9'

который исправляет мою проблему. Может кто-нибудь объяснить мне, что именно происходит?

Ответ 1

Кажется, вы сбили свои кодировки. Кажется вероятным, что вы действительно хотите u'Andr\xe9', что эквивалентно 'André'.

Но то, что у вас есть, является кодировкой UTF-8, которая была неправильно декодирована. Вы можете исправить это, преобразовая строку юникода в обычную строку. Я не уверен, что лучший способ, но это, похоже, работает:

>>> ''.join(chr(ord(c)) for c in u'Andr\xc3\xa9')
'Andr\xc3\xa9'

Затем правильно декодируйте его:

>>> ''.join(chr(ord(c)) for c in u'Andr\xc3\xa9').decode('utf8')
u'Andr\xe9'    

Теперь он находится в правильном формате.

Однако вместо этого, если это возможно, вы должны попытаться выяснить, почему данные были некорректно закодированы в первую очередь, и устранить эту проблему.

Ответ 2

Вы спросили (в комментарии) "Это то, что меня озадачило. Как это исходило из оригинального акцента на то, что теперь? Когда вы говорите двойную кодировку с utf8 и latin1, это всего три кодировки (2 utf8 + 1 latin1)? Каков порядок кодирования от исходного состояния до текущего? "" "

В ответе Марка Байерса он говорит "" " то, что у вас похоже на кодировку UTF-8, которая была неправильно декодирована "". Вы приняли его ответ. Но вы все еще озадачены? ОК, здесь описание "удар по воздуху":

Примечание. Все строки будут отображаться с использованием (неявно) repr(). unicodedata.name() будет использоваться для проверки содержимого. Таким образом, вариации в консольной кодировке не могут путать интерпретацию строк.

Исходное состояние: у вас есть объект unicode, который вы назвали u1. Он содержит e-sharp:

>>> u1 = u'\xe9'
>>> import unicodedata as ucd
>>> ucd.name(u1)
'LATIN SMALL LETTER E WITH ACUTE'

Вы кодируете u1 как UTF-8 и называете результат s:

>>> s = u1.encode('utf8')
>>> s
'\xc3\xa9'

Вы декодируете s с использованием latin1 - НЕПРАВИЛЬНО; s был закодирован с использованием utf8, NOT latin1. Результатом является бессмысленный мусор.

>>> u2 = s.decode('latin1')
>>> u2
u'\xc3\xa9'
>>> ucd.name(u2[0]); ucd.name(u2[1])
'LATIN CAPITAL LETTER A WITH TILDE'
'COPYRIGHT SIGN'
>>>

Пожалуйста, поймите: unicode_object.encode('x').decode('y), когда x!= y обычно [см. примечание ниже], нонсенс; это вызовет исключение, если вам повезет; если вам не повезло, он будет бесшумно создавать тарабарщину. Также, пожалуйста, поймите, что бесшумное создание тарабарщины не является ошибкой - нет общего способа, которым Python (или любой другой язык) может обнаружить, что взятка была совершена. Это особенно важно, когда задействован latin1, потому что все 256 кодовых точек сопоставляют 1 к 1 с первыми 256 кодовыми точками Unicode, поэтому невозможно получить UnicodeDecodeError из str_object.decode('latin1').

Конечно, ненормально (можно надеяться, что это ненормально), вам может потребоваться отменить такую ​​глупость, сделав gibberish_unicode_object.encode('y').decode('x'), как это предлагается в различных ответах на ваш вопрос.

Ответ 4

OP не преобразуется в ascii или utf-8. Поэтому предложенные методы encode не будут работать. Попробуйте следующее:

v = u'Andr\xc3\xa9'
s = ''.join(map(lambda x: chr(ord(x)),v))

Бизнес chr(ord(x)) получает числовое значение символа юникода (которое лучше подходит для одного байта для вашего приложения), а вызов ''.join - это идиома, которая преобразует список ints обратно в обычную строку. Несомненно, есть более элегантный способ.

Ответ 5

Если у вас u'Andr\xc3\xa9', это, скорее всего, первоначально UTF-8 из любого источника, из которого он был получен. Если возможно, прочитайте исходный код с расширением "utf-8". В противном случае просто переверните ошибку:

>>> print u'Andr\xc3\xa9'.encode('latin-1').decode('utf-8')
André

Ответ 6

Упрощенное объяснение. Тип str может содержать только символы из диапазона 0-255. Если вы хотите сохранить unicode (который может содержать символы из более широкого диапазона) на str, вам сначала нужно кодировать unicode для форматирования, подходящего для str, например UTF-8.

Чтобы сделать этот метод вызова закодирован на вашем объекте str и в качестве аргумента укажите желаемую кодировку, например this_is_str = value_uni.encode('utf-8').

Вы можете прочитать более длинную и более детальную (и язык агностик) статью об использовании Юникода здесь: Абсолютный минимум Каждый разработчик программного обеспечения Абсолютно, положительно должен знать О Unicode и наборах символов (нет оправданий!).

Еще одна отличная статья (на этот раз Python): Unicode HOWTO

Ответ 7

Кажется,

str(value_uni)

должен работать... по крайней мере, это было, когда я это пробовал.

EDIT: Оказывается, это работает только потому, что моя системная кодировка по умолчанию является, насколько я могу судить, ISO-8859-1 (Latin-1). Поэтому для независимой от платформы версии, попробуйте

value_uni.encode('latin1')