40

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

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

我的输入字符串是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)

探索问题原因: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))

异常的原因是 in ''.join(map(quoter, s)),对于 s 中的每个元素,都会调用 quoter 函数,最后将列表以 '' 连接并返回。

对于非 ascii char è,等效键将是变量%E8中出现的键。_safe_map但是当我调用 quote('è') 时,它会搜索 key \xe8。使键不存在并抛出异常。

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

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

4

3 回答 3

63

您正在尝试引用 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'

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

于 2013-02-27T15:19:23.247 回答
2

通过将字符串转换为 unicode,我解决了这个问题。

这是片段:

try:
    unicode(mystring, "ascii")
except UnicodeError:
    mystring = unicode(mystring, "utf-8")
else:
    pass

解决方案的详细描述可以在http://effbot.org/pyfaq/what-does-unicodeerror-ascii-decoding-encoding-error-ordinal-not-in-range-128-mean.htm找到

于 2013-12-17T11:42:26.807 回答
1

我有与@underscore 完全相同的错误,但在我的情况下,问题是 map(quoter,s) 试图查找u'\xe9'不在_safe_map. 但是,所以我通过\xe9替换in解决了这个问题。u'\xe9'\xe9s

此外,return语句不应该在try/except? 我还必须更改它以完全解决问题。

于 2015-07-28T14:51:35.060 回答