Ответ 1
Хороший вопрос. Проблемы с кодированием сложны. Давайте начнем с "У меня есть строка". Строки в Python 2 на самом деле не являются "строками", это байтовые массивы. Итак, ваша строка, откуда она взялась и в какой кодировке? В вашем примере показаны фигурные кавычки в буквальном значении, и я даже не знаю, как вы это сделали. Я пытаюсь вставить его в интерпретатор Python или набрать его на OS X с Option- [, и он не пройдет.Если вы посмотрите на свой второй пример, у вас есть символ hex 93. Это не может быть UTF-8, потому что в UTF-8 любой байт выше 127 является частью многобайтового последовательность. Поэтому я предполагаю, что он должен быть латинским-1. Проблема в том, что x93 не является символом в наборе символов Latin-1. Там этот "недопустимый" диапазон в латинском-1 от x7f до x9f считается незаконным. Тем не менее, Microsoft увидела этот неиспользованный диапазон и решила поставить там "кудрявые цитаты". При этом они создали подобную кодировку под названием "windows-1252", которая похожа на Latin-1 с материалом в этом недопустимом диапазоне.
Итак, допустим, что это windows-1252. Что теперь? String.decode преобразует байты в Юникод, так что тот, который вы хотите. Второй пример был на правильном пути, но он не удался, потому что строка не была 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, хотя они не имеют курсорных котировок.