Как декодировать encodeURIComponent в GAE (python)? - PullRequest
10 голосов
/ 27 марта 2012

У меня есть строка Unicode, которая была закодирована на стороне клиента с использованием JS encodeURIComponent.

Если я использую в Python следующее, я получаю ожидаемый результат:

>>> urllib.unquote("Foo%E2%84%A2%20Bar").decode("utf-8")
>>> u'Foo\u2122 Bar'

Нокогда я запускаю это в Google App Engine, я получаю:

Traceback (most recent call last):
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/_webapp25.py", line 703, in __call__
    handler.post(*groups)
  File "/base/data/home/apps/s~kaon-log/2.357769827131038147/main.py", line 143, in post
    path_uni = urllib.unquote(h.path).decode('utf-8')
  File "/base/python_runtime/python_dist/lib/python2.5/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 3-5: ordinal not in range(128)

Я все еще использую Python 2.5, на случай, если что-то изменится.Чего мне не хватает?

Ответы [ 2 ]

9 голосов
/ 27 марта 2012

Я предполагаю, что h.path - это объект Unicode.Тогда urllib.unquote вернет объект в кодировке Unicode.Когда decode вызывается в Unicode-объекте сначала, он преобразуется в str с использованием кодировки по умолчанию (которая является ascii), и здесь вы получаете исключение 'ascii' codec can't encode.

Вот доказательство:

>>> urllib.unquote(u"Foo%E2%84%A2%20Bar").decode("utf-8")
...
UnicodeEncodeError: 'ascii' codec can't encode characters in position 3-5: ordinal not in range(128)

Это должно сработать:

urllib.unquote(h.path.encode('utf-8')).decode("utf-8")

Существует поток стекового потока, который объясняет, почему Юникод не работает с urllib.unquote: Как снять кавычки в кодировке строки Юникода в python

0 голосов
/ 20 августа 2014

Используйте этот класс вместо urllib2:

class URL(object):
  '''encode/decode requested URL'''
  def __init__(self):
    self.charset = '/abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789.'

  def encode(self,url):
    return ''.join([c if c in self.charset else '%'+c.encode('hex').upper() for c in url])

  def decode(self,url):
    return re.compile('%([0-9a-fA-F]{2})',re.M).sub(lambda m: chr(int(m.group(1),16)), url)

Пример:

  import re
  URL().decode(your URL)
...