urllib.quote()抛出KeyError

Gar*_*eld 39 python unicode urllib urlencode urllib2

为了对URI进行编码,我使用urllib.quote("schönefeld")但是当字符串中存在一些非ascii字符时,它就是Thorws

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

我的输入字符串köln, brønshøj, schönefeld等.

当我尝试在Windows中打印语句时(使用python2.7,pyscripter IDE).但是在linux中它会引发异常(我猜平台并不重要).

这就是我想要的:

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

探索问题的原因: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))
Run Code Online (Sandbox Code Playgroud)

异常的原因在于''.join(map(quoter, s)),对于s中的每个元素,将调用引号函数,最后列表将由''连接并返回.

对于非ASCII字符,è,等效关键是%E8在其中呈现_safe_map的变量.但是当我打电话报价('è')时,它会搜索密钥\xe8.这样键就不存在而抛出异常.

所以,我在调试try-except块s = [el.upper().replace("\\X","%") for el in s]之前修改了''.join(map(quoter, s))一下.现在它工作正常.

但我很烦恼我所做的是正确的方法还是会产生任何其他问题?而且我确实有200多个Linux实例,在所有实例中部署此修复程序非常困难.

Mar*_*ers 60

您正在尝试引用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'
Run Code Online (Sandbox Code Playgroud)

但是,编码取决于服务器将接受的内容.最好坚持原始表单发送的编码.