wsgi - обработка символов юникода из поста - PullRequest
2 голосов
/ 26 сентября 2011

питон 2.7

raw = '%C3%BE%C3%A6%C3%B0%C3%B6' #string from wsgi post_data
raw_uni = raw.replace('%', r'\x')
raw_uni # gives '\\xC3\\xBE\\xC3\\xA6\\xC3\\xB0\\xC3\\xB6'
print raw uni #gives '\xC3\xBE\xC3\xA6\xC3\xB0\xC3\xB6'
uni = unicode(raw_uni, 'utf-8')
uni #gives u'\\xC3\\xBE\\xC3\\xA6\\xC3\\xB0\\xC3\\xB6+\\xC3\\xA9g'
print uni #gives \xC3\xBE\xC3\xA6\xC3\xB0\xC3\xB6+\xC3\xA9g

Однако, если я изменю raw_uni на:

raw_uni = '\xC3\xBE\xC3\xA6\xC3\xB0\xC3\xB6'

и теперь сделайте:

uni = unicode(raw_uni, 'utf-8')
uni #gives u'\xfe\xe6\xf0\xf6'
print uni #gives þæðö

что я и хочу.

как мне избавиться от этого лишнего '\' в raw_uni или воспользоваться тем, что он есть только в repr-версии строки? Более конкретно, почему Юникод (raw_uni, 'utf-8') использует версию строки repr ???

спасибо

1 Ответ

3 голосов
/ 26 сентября 2011

Вы должны использовать urllib.unquote, а не ручную замену:

>>> import urllib
>>> raw = '%C3%BE%C3%A6%C3%B0%C3%B6'
>>> urllib.unquote(raw)
'\xc3\xbe\xc3\xa6\xc3\xb0\xc3\xb6'
>>> unicode(urllib.unquote(raw), 'utf-8')
u'\xfe\xe6\xf0\xf6'

Основная проблема здесь заключается в том, что у вас есть фундаментальное неправильное понимание того, что такое шестнадцатеричные побеги.repr непечатаемого символа может быть выражен как шестнадцатеричный escape, который выглядит как одиночная обратная косая черта, за которой следует «x», за которым следуют два шестнадцатеричных символа.Это также, как вы могли бы ввести эти символы в строковый литерал, но это все еще только один символ.Ваша строка replace не превращает вашу исходную строку в шестнадцатеричные экранированные символы, она просто заменяет каждый «%» буквальным символом обратной косой черты, за которым следует «x».

Рассмотрим следующие примеры:

>>> len('\xC3')         # this is a hex escape, only one character
1
>>> len(r'\xC3')        # this is four characters, '\', 'x', 'C', '3'
4
>>> r'\xC3' == '\\xC3'  # raw strings escape backslashes
True

Если по какой-то причине вы не можете использовать urllib.unquote, должно работать следующее:

raw_uni = re.sub('%(\w{2})', lambda m: chr(int(m.group(1), 16)), raw)
...