Я пытаюсь кодировать, хранить и декодировать аргументы в Python и теряюсь где-то по пути. Вот мои шаги:
1) Я использую gtm_stringByEscapingForURLArgument из набора инструментов google для правильного преобразования строки NSString для передачи в аргументы HTTP.
2) На моем сервере (python) я храню эти строковые аргументы как что-то вроде u'1234567890 - / :; () $ & @ ".,?! \ '[] {} #% ^ * + = _ \\ |.?! ~ <> \ u20ac \ XA3 \ xa5 \ u2022 \ ''
(обратите внимание, что это стандартные клавиши на клавиатуре iphone в представлениях «123» и «# + =», символы \ u
и \ x
в существуют некоторые денежные префиксы, такие как фунт, иена и т. д.)
3) я вызываю urllib.quote (myString, '')
для этого хранимого значения, предположительно в% -ecape их для передачи клиенту таким образом, клиент может избежать их сброса.
В результате я получаю исключение, когда пытаюсь записать результат% escape. Есть ли какой-то важный шаг, который я пропускаю, который нужно применить к сохраненному значению в формате \ u и \ x, чтобы правильно преобразовать его для отправки по http?
Обновление : предложение, помеченное как ответ ниже работал для меня. Я предоставляю некоторые обновления, чтобы ответить на комментарии ниже, чтобы быть полным, хотя.
Исключение, которое я получил, ссылается на проблему с \ u20ac
. Я не знаю, была ли проблема именно с этим, а не с тем фактом, что это был первый символ Unicode в строке.
То, что \ u20ac
char - это Unicode для «евро». символ. В основном я обнаружил, что у меня возникли бы проблемы с этим, если бы я не использовал метод urllib2 quote
.
URL, кодирующий «сырой» юникод, на самом деле не имеет смысла. Что вам нужно сделать, так это .encode("utf8")
сначала, чтобы у вас была известная кодировка байтов, а затем .quote()
.
Вывод не очень красивый, но это должна быть правильная кодировка uri.
>>> s = u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\|~<>\u20ac\xa3\xa5\u2022.,?!\''
>>> urllib2.quote(s.encode("utf8"))
'1234567890-/%3A%3B%28%29%24%26%40%22.%2C%3F%21%27%5B%5D%7B%7D%23%25%5E%2A%2B%3D_%5C%7C%7E%3C%3E%E2%82%AC%C2%A3%C2%A5%E2%80%A2.%2C%3F%21%27'
Помните, что вам потребуется как unquote()
, так и decode()
это, чтобы распечатать его правильно, если вы отлаживаете или что-то еще.
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8")))
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'
>>> # oops, nasty  means we've got a utf8 byte stream being treated as an ascii stream
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8"))).decode("utf8")
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'
Это, по сути, то, что делают функции джанго, упомянутые в другом ответе.
Функции django.utils.http.urlquote() и django.utils.http.urlquote_plus() являются версии стандарта Python urllib.quote() и urllib.quote_plus() которые работают с символами, отличными от ASCII. (данные конвертируются в UTF-8 перед к кодировке.)
Будьте осторожны, если вы применяете какие-либо дополнительные кавычки или кодировки, чтобы не испортить что-то.
Вам не повезло со stdlib, urllib.quote не работает с юникодом. Если вы используете django, вы можете использовать django.utils.http.urlquote, который правильно работает с юникодом
Я хочу поддержать замечание Пикруфта. Веб-протоколы развивались десятилетиями, и работа с различными наборами соглашений может быть обременительной. теперь URL-адреса явно не определены для символов, а только для байтов (октетов). как историческое совпадение, URL-адреса являются одним из мест, где вы можете только предполагать, но не применять или безопасно ожидать присутствия кодировки. однако здесь принято отдавать предпочтение latin-1 и utf-8 другим кодировкам. какое-то время казалось, что «процентные побеги юникода» будут в будущем, но они так и не прижились.
Крайне важно быть педантично разборчивым в этой области в отношении различий между объектами unicode
и октетами строками
(в Python < 3.0; это, как ни странно, объекты unicode str
и объекты bytes
/bytearray
в Python >= 3.0). к сожалению, по моему опыту, по ряду причин довольно сложно четко разделить две концепции в Python 2.x.
еще больше OT, когда вы хотите получать сторонние HTTP-запросы, вы не можете полностью полагаться на URL-адреса, отправляемые в октетах с процентным экранированием и кодировкой utf-8: могут быть оба случайных %uxxxx
escape там, и, по крайней мере, Firefox 2.x используется для кодирования URL-адресов как latin-1, где это возможно, и как utf-8 только там, где это необходимо.