Хороший вопрос. Проблемы с кодированием возникают непросто. Начнем с «У меня есть строка». Строки в Python 2 на самом деле не «строки», это массивы байтов. Итак, ваша строка, откуда она взялась и в какой она кодировке? В вашем примере фигурные кавычки показаны буквально, и я даже не уверен, как вы это сделали. Я пытаюсь вставить его в интерпретатор Python или набираю его в OS X с помощью Option- [, но ничего не выходит.
Если посмотреть на второй пример, у вас есть шестнадцатеричный символ 93. Это не может быть UTF-8 , потому что в UTF-8 любой байт выше 127 является частью многобайтовой последовательности. . Полагаю, это должна быть Latin-1. Проблема в том, что x93 не является символом в наборе символов Latin-1. В Latin-1 есть «недопустимый» диапазон от x7f до x9f, который считается незаконным. Однако Microsoft увидела этот неиспользуемый диапазон и решила поместить туда «фигурные кавычки». При этом они создали аналогичную кодировку под названием «windows-1252», которая похожа на Latin-1 с вещами в этом недопустимом диапазоне.
Итак, предположим, что это windows-1252 . Что теперь? String.decode преобразует байты в Unicode, так что это тот, который вам нужен. Ваш второй пример был на правильном пути, но он не удался, потому что строка не была UTF-8. Попробуйте:
>>> uni = 'foo \x93bar bar\x94 weasel'.decode("windows-1252")
u'foo \u201cbar bar\u201d weasel'
>>> print uni
foo “bar bar” weasel
>>> type(uni)
<type 'unicode'>
Это правильно, потому что открывающая фигурная кавычка - это Unicode U + 201C. Теперь, когда у вас есть Unicode, вы можете сериализовать его в байты в любой кодировке по вашему выбору (если вам нужно передать его по сети) или просто сохранить его как Unicode, если он остается в Python. Если вы хотите преобразовать в UTF-8, используйте функцию oppose, string.encode.
>>> uni.encode("utf-8")
'foo \xe2\x80\x9cbar bar \xe2\x80\x9d weasel'
Фигурные кавычки требуют 3 байта для кодирования в UTF-8. Вы можете использовать UTF-16, и это будет всего два байта. Вы не можете кодировать как ASCII или Latin-1, потому что у них нет фигурных кавычек.
EDIT. Похоже, что ваша строка закодирована таким образом, что "
(ЛЕВАЯ ДВУХКВАРТИРНАЯ МАРКА) становится \x93
, а "
(ПРАВАЯ ДВУХКВАРТИРНАЯ МАРКА) становится \x94
. Существует ряд кодовых страниц с таким отображением, CP1250 - одна из них, поэтому вы можете использовать это:
s = s.decode('cp1250')
Все кодовые страницы, которые отображают "
на \x93
смотрите здесь (все они также отображают "
на \x94
, что можно проверить здесь).