【问题标题】:How to decode encodeURIComponent in GAE (python)?如何在 GAE(python)中解码 encodeURIComponent?
【发布时间】:2026-02-01 05:45:01
【问题描述】:

我有一个在客户端使用 JS encodeURIComponent 编码的 unicode 字符串。

如果我在本地 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,以防万一。我错过了什么?

【问题讨论】:

    标签: python google-app-engine unicode character-encoding uri


    【解决方案1】:

    我的猜测是 h.path 是一个 unicode 对象。然后urllib.unquote 将返回一个 unicode 对象。当 decode 最初在 unicode 对象上调用时,它会使用默认编码(即 ascii)转换为 str,在这里你会得到 '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")
    

    有一个 * 线程解释了为什么 unicode 不能与 urllib.unquote 一起使用:How to unquote a urlencoded unicode string in python?

    【讨论】:

    • 我使用了 urllib.unquote(str(h.path)).decode("utf-8") 并且成功了。
    【解决方案2】:

    使用这个类代替 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)
    

    【讨论】:

    • 你能解释一下原因吗?