【问题标题】:UnicodeDecodeError is raised when getting a cookie in Google App Engine在 Google App Engine 中获取 cookie 时引发 UnicodeDecodeError
【发布时间】:2011-10-13 23:20:10
【问题描述】:

我在 Python 中有一个 GAE 项目,我正在使用以下代码在我的一个 RequestHandlers 中设置一个 cookie:

self.response.headers['Set-Cookie'] = 'app=ABCD; expires=Fri, 31-Dec-2020 23:59:59 GMT'

我在 Chrome 中进行了检查,可以看到列出的 cookie,因此它似乎可以正常工作。

然后在另一个 RequestHandler 中,我得到 cookie 来检查它:

appCookie = self.request.cookies['app']

此行在执行时会出现以下错误:

UnicodeDecodeError:“ascii”编解码器无法解码位置 1962 中的字节 0xe2:序数不在范围内(128)

它似乎正在尝试使用 ASCII 编解码器而不是 UTF-8 解码传入的 cookie 信息。

如何强制 Python 使用 UTF-8 对其进行解码?

作为 Python 和 Google App Engine 的新手(但对于其他语言的经验丰富的程序员),我是否需要了解其他与 Unicode 相关的问题?

这是完整的回溯:

Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 4144, in _HandleRequest
    self._Dispatch(dispatcher, self.rfile, outfile, env_dict)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 4049, in _Dispatch
    base_env_dict=env_dict)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 616, in Dispatch
    base_env_dict=base_env_dict)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 3120, in Dispatch
    self._module_dict)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 3024, in ExecuteCGI
    reset_modules = exec_script(handler_path, cgi_path, hook)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver.py", line 2887, in ExecuteOrImportScript
    exec module_code in script_module.__dict__
  File "/Users/ken/hgdev/juicekit/main.py", line 402, in <module>
    main()
  File "/Users/ken/hgdev/juicekit/main.py", line 399, in main
    run_wsgi_app(application)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/util.py", line 98, in run_wsgi_app
    run_bare_wsgi_app(add_wsgi_middleware(application))
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/util.py", line 116, in run_bare_wsgi_app
    result = application(env, _start_response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/__init__.py", line 721, in __call__
    response.wsgi_write(start_response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/__init__.py", line 296, in wsgi_write
    body = self.out.getvalue()
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/StringIO.py", line 270, in getvalue
    self.buf += ''.join(self.buflist)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1962: ordinal not in range(128)

【问题讨论】:

  • 能否请您包含完整的堆栈跟踪信息?该问题可能出现在许多地方,完整的堆栈跟踪提供了更多详细信息。
  • 就 Python 中的 Unicode 而言,请参见此处:blog.notdot.net/2010/07/Getting-unicode-right-in-Python
  • 您的 cookie 中没有非 ASCII 字符(或位置 1962),因此您显示的代码完全不可能实际抛出该错误。
  • 感谢 Wooble 的建设性和有益的回复。不幸的是,您的陈述毫无意义,因为代码实际上抛出了我所说的错误。不理解不代表不可能。
  • 嗨尼克...添加了完整的追溯。谢谢。

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


【解决方案1】:

首先,对您在 cookie 中设置的任何 unicode 值进行编码。您还需要引用它们以防它们破坏标题:

import urllib

# This is the value we want to set.
initial_value = u'äëïöü'
# WebOb version that comes with SDK doesn't quote cookie values
# in the Response, neither webapp.Response. So we have to do it.
quoted_value = urllib.quote(initial_value.encode('utf-8'))

rsp = webapp.Response()
rsp.headers['Set-Cookie'] = 'app=%s; Path=/' % quoted_value

现在让我们读取值。为了测试它,创建一个假的Request 来测试我们设置的cookie。这段代码是从一个真实的单元测试中提取的:

cookie = rsp.headers.get('Set-Cookie')
req = webapp.Request.blank('/', headers=[('Cookie', cookie)])

# The stored value is the same quoted value from before.
# Notice that here we use .str_cookies, not .cookies.
stored_value = req.str_cookies.get('app')
self.assertEqual(stored_value, quoted_value)

我们的值仍然被编码和引用。我们必须做相反的事情来得到最初的:

# And we can get the initial value unquoting and decoding.
final_value = urllib.unquote(stored_value).decode('utf-8')
self.assertEqual(final_value, initial_value)

如果可以,请考虑使用webapp2webob.Response 完成了所有引用和设置 cookie 的繁重工作,您可以直接设置 unicode 值。查看这些问题的摘要here

【讨论】:

    【解决方案2】:

    您希望像这样使用decode 函数(cred @agf:):

    self.request.cookies['app'].decode('utf-8')
    

    From official python documentation(加上一些附加细节):

    Python 的 8 位字符串有一个 .decode([encoding], [errors]) 方法,它使用给定的编码来解释字符串。以下示例显示了字符串转为 unicode,然后返回 8 位字符串:

    >>> u = unichr(40960) + u'abcd' + unichr(1972)   # Assemble a string
    >>> type(u), u                                   # Examine
    (<type 'unicode'>, u'\ua000abcd\u07b4')
    >>> utf8_version = u.encode('utf-8')             # Encode as UTF-8
    >>> type(utf8_version), utf8_version             # Examine
    (<type 'str'>, '\xea\x80\x80abcd\xde\xb4')
    >>> u2 = utf8_version.decode('utf-8')            # Decode using UTF-8
    >>> u == u2                                      # The two strings match
    True
    

    【讨论】:

    • 这能解决他的问题吗?他能做到self.request.cookies['app'].encode('utf-8')吗?
    • @agf:更多的是一个示范性的例子。但我想我应该记下他必须使用哪些功能。谢谢。
    • 感谢您的想法,但这无济于事。我得到同样的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 2015-05-18
    • 2011-12-27
    • 1970-01-01
    相关资源
    最近更新 更多