Подтвердить что ты не робот

Urllib.quote() бросает KeyError

Чтобы закодировать URI, я использовал urllib.quote("schönefeld"), но когда в строке присутствуют некоторые символы, отличные от ascii, он поддерживает

KeyError: u'\xe9'
Code: return ''.join(map(quoter, s))

Мои строки ввода köln, brønshøj, schönefeld и т.д.

Когда я пробовал просто печатать заявления в окнах (с использованием python2.7, pyscripter IDE). Но в Linux он вызывает исключение (я думаю, платформа не имеет значения).

Вот что я пытаюсь:

from commands import getstatusoutput
queryParams = "schönefeld";
cmdString = "http://baseurl" + quote(queryParams)
print getstatusoutput(cmdString)

Изучение причины проблемы: в urllib.quote(), на самом деле исключение выбрано в return ''.join(map(quoter, s)).

Код в urllib:

def quote(s, safe='/'):
    if not s:
        if s is None:
            raise TypeError('None object cannot be quoted')
        return s
     cachekey = (safe, always_safe)
     try:
         (quoter, safe) = _safe_quoters[cachekey]
     except KeyError:
         safe_map = _safe_map.copy()
         safe_map.update([(c, c) for c in safe])
         quoter = safe_map.__getitem__
         safe = always_safe + safe
         _safe_quoters[cachekey] = (quoter, safe)
      if not s.rstrip(safe):
         return s
      return ''.join(map(quoter, s))

Причиной исключения является ''.join(map(quoter, s)), для каждого элемента из s будет вызываться функция-циферблат, и, наконец, список будет соединен с символом '' и возвращен.

Для non-ascii char è эквивалентный ключ будет %E8, который представлен в переменной _safe_map. Но когда я вызываю цитату ('è'), она ищет ключ \xe8. Так что ключ не существует и исключение выбрано.

Итак, я просто модифицировал s = [el.upper().replace("\\X","%") for el in s] перед вызовом ''.join(map(quoter, s)) в блоке try-except. Теперь он отлично работает.

Но я раздражаю то, что я сделал, это правильный подход или он создаст любую другую проблему? А также у меня есть 200+ экземпляров Linux, которые очень сложно развернуть это исправление во всех случаях.

4b9b3361

Ответ 1

Вы пытаетесь указать данные Unicode, поэтому вам нужно решить, как превратить это в безопасные по URL-адреса байты.

Сначала кодируйте строку в байты. UTF-8 часто используется:

>>> import urllib
>>> urllib.quote(u'sch\xe9nefeld')
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py:1268: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
  return ''.join(map(quoter, s))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 1268, in quote
    return ''.join(map(quoter, s))
KeyError: u'\xe9'
>>> urllib.quote(u'sch\xe9nefeld'.encode('utf8'))
'sch%C3%A9nefeld'

Однако кодировка зависит от того, что сервер примет. Лучше всего придерживаться кодировки, с которой была отправлена ​​оригинальная форма.

Ответ 3

У меня была такая же ошибка, как и @underscore, но в моем случае проблема заключалась в том, что карта (quoter, s) пыталась найти ключ u'\xe9', который не был в _safe_map. Однако \xe9 был, поэтому я решил проблему, заменив u'\xe9' на \xe9 в s.

Кроме того, должен ли оператор return находиться в пределах try/except? Мне также пришлось изменить это, чтобы полностью решить проблему.