Как преобразовать 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')
, как это предлагается в различных ответах на ваш вопрос.
Ответ 3
value_uni.encode('utf8')
или любую необходимую вам кодировку.
См. http://docs.python.org/library/stdtypes.html#str.encode
Ответ 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')