«Сломанные» строки юникода, закодированные в UTF-8? - PullRequest
3 голосов
/ 10 марта 2010

Я уже два дня изучаю юникод и его реализацию на Python, и думаю, что я понимаю, о чем он. Просто чтобы быть уверенным, я спрашиваю, верны ли мои предположения относительно моих текущих проблем.

В Django формы дают мне юникодные строки, которые я подозреваю, что они "сломаны" Unicode-строки в Python должны быть закодированы в UTF-8, верно? После ввода строки "fähre" в текстовое поле браузер отправляет строку "f% c3% a4hre" в запросе POST (проверяется с помощью wireshark). Когда я получаю значение через form.cleaned_data, я получаю строку u'f \ xa4hre '(обратите внимание, что это строка в кодировке Unicode). Насколько я понимаю, это Unicode-строка в кодировке ISO-8859-1, что неверно. Правильная строка должна быть u'f \ xc3 \ xa4hre ', которая будет строкой Unicode в кодировке UTF-8. Это ошибка в Django или в моем понимании что-то не так? Чтобы решить эту проблему, я написал функцию для применения к любому вводу текста из форм Django:

def fix_broken_unicode(s):
    return unicode(s.encode(u'utf-8'), u'iso-8859-1')

что делает

>>> fix_broken_unicode(u'f\xa4hre')
u'f\xc3\xa4hre'

Это не кажется мне очень элегантным, но установка параметров Django.DEFAULT_CHARSET в значение 'utf-8' не помогла, как и ничего другого. Я пытаюсь работать с юникодом по всему приложению, чтобы потом не было никаких странных ошибок, но этого явно недостаточно, чтобы пометить все строки как '...'.

Редактировать: Учитывая ответы Дирка и STH, теперь я сохраню строки в базе данных, как они есть. Реальная проблема заключалась в том, что я пытался кодировать эти типы строк, чтобы использовать их в качестве входных данных для API Twitter и т. Д. Однако в запросах GET или POST, очевидно, ожидается кодирование UTF-8, что делает стандартная функция urllib.urlencode () не обрабатывается правильно (выбрасывает исключения). Посмотрите на мое решение в pastebin и не стесняйтесь комментировать его.

Ответы [ 2 ]

4 голосов
/ 10 марта 2010

u'f\xa4hre' - строка в кодировке Unicode, не закодированная как что-либо. Код Unicode 0xa4 - это символ ä. Не очень важно, чтобы ä также кодировался как байт 0xa4 в ISO-8859-1.

Строка Unicode может содержать любые символы Unicode без какого-либо кодирования. Например, 轮渡 будет представлен как u'\u8f6e\u6e21', которые являются просто двумя кодовыми точками Юникода. Кодировка UTF-8 будет намного длиннее '\xe8\xbd\xae\xe6\xb8\xa1'.

Так что нет необходимости исправлять кодировку, вы просто видите внутреннее представление строки Unicode.

1 голос
/ 10 марта 2010

Не совсем: после декодирования строка Unicode будет Unicode , что означает, что она может содержать символы с кодами, превышающими 255. То, как интерпретатор представляет их, зависит от платформы, но обычно в настоящее время он использует элементы шириной не менее 16 бит. ISO-8859-1 является правильным подмножеством юникода. Таким образом, строка u'f\xa4hre' на самом деле правильная - \xa4 является артефактом рендеринга, поскольку Python не знает, безопасно ли (и когда) включать символы с кодами, выходящими за пределы определенного диапазона на консоли.

UTF-8 - это транспортная кодировка , то есть особый способ записи данных в Unicode таким образом, что они могут храниться в «каналах» с шириной элемента 8 бит на символ / байт. Чтобы вычислить правильную «внешнюю» (или транспортную) кодировку строки Unicode, вы должны использовать метод encode, передавая желаемое представление. Он возвращает правильно закодированную строку байтов (в отличие от строки символов Unicode).

Обратное преобразование - decode, которое принимает строку байтов и имя кодировки и выдает Unicode строку символов .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...