【问题标题】:Pyramid on App Engine gets "InvalidResponseError: header values must be str, got 'unicode'App Engine 上的 Pyramid 获取“InvalidResponseError:标头值必须是 str,得到 'unicode'
【发布时间】:2014-04-09 13:40:38
【问题描述】:

我在 OS X 10.7.3 上使用 Pyramid 1.3 和 AppEngine 1.6.4 SDK。我正在使用 Python 2.7 并在 app.yaml 中设置了线程安全。

@view_config(route_name='manager_swms', permission='manager', renderer='manager/swms.jinja2')
def manager_swms(request):
    """Generates blobstore url and passes users swms in swms table"""

    # generate url for any form upload that may occur
    upload_url = blobstore.create_upload_url('/upload_swm')

    user = get_current_user(request)
    swms = DBSession.query(SWMS).filter_by(owner_id=int(user.id)).all()

    return {
        "analytics_id": analytics_id,
        "user": get_current_user(request),
        "upload_url": upload_url,
        "swms": [(x.filename, x.blob_key) for x in swms]
    }

class BlobstoreUploadHandler(object):
    """Base class for creation blob upload handlers."""

    def __init__(self, *args, **kwargs):
        self.__uploads = None

    def get_uploads(self, field_name=None):
        """Get uploads sent to this handler.

        Args:
          field_name: Only select uploads that were sent as a specific field.

        Returns:
          A list of BlobInfo records corresponding to each upload.
          Empty list if there are no blob-info records for field_name.
        """
        if self.__uploads is None:
            self.__uploads = {}
            for key, value in self.request.params.items():
                if isinstance(value, cgi.FieldStorage):
                    if 'blob-key' in value.type_options:
                        self.__uploads.setdefault(key, []).append(
                            blobstore.parse_blob_info(value))

        if field_name:
            try:
                return list(self.__uploads[field_name])
            except KeyError:
                return []
        else:
            results = []
            for uploads in self.__uploads.itervalues():
                results += uploads
            return results

@view_config(route_name='upload_swm', permission='manager')
class UploadHandler(BlobstoreUploadHandler):
    ''' Handles redirects from Blobstore uploads. '''

    def __init__(self, request):
        self.request = request
        super(UploadHandler, self).__init__()

    def __call__(self):

        user = get_current_user(self.request)
        for blob_info in self.get_uploads('file'):

            new_swm = SWMS(
                owner_id = int(user.id),
                blob_key = str(blob_info.key()),
                filename = blob_info.filename,
                size = blob_info.size,
            )
            DBSession.add(new_swm)
        DBSession.flush()

        # redirect to swms page
        return HTTPFound(location='/manager/swms')

在上面的代码中,manager_swms() 生成一个页面,其中包含一个用于将文件上传到 Blobstore 的表单。表单工作正常,使用表单时,我可以看到 Blob 出现在 Blobstore 中。然后从 blobstore POST 重定向到 /upload_swm,我在其中成功获取 BlobInfo 详细信息并将它们放入 SQL 表中。这一切都很好,我要做的最后一件事是重定向到第一页,以便在需要时可以上传另一个文件,我可以显示上传的文件列表。

根据 Pyramid 文档,我正在使用 HTTPFound(location='/manager/swms') [原始页面 URL] 尝试重定向,但是我得到了:

ERROR    2012-03-29 22:56:38,170 wsgi.py:208] 
Traceback (most recent call last):
  File "/Users/tim/work/OHSPro/var/parts/google_appengine/google/appengine/runtime/wsgi.py", line 196, in Handle
    result = handler(self._environ, self._StartResponse)
  File "lib/dist/pyramid/router.py", line 195, in __call__
    foo = response(request.environ, start_response)
  File "lib/dist/pyramid/httpexceptions.py", line 291, in __call__
    foo = Response.__call__(self, environ, start_response)
  File "lib/dist/webob/response.py", line 922, in __call__
    start_response(self.status, headerlist)
  File "/Users/tim/work/OHSPro/var/parts/google_appengine/google/appengine/runtime/wsgi.py", line 150, in _StartResponse
    _GetTypeName(header[1]))
InvalidResponseError: header values must be str, got 'unicode'
INFO     2012-03-29 22:56:38,174 dev_appserver_blobstore.py:408] Upload handler returned 500
INFO     2012-03-29 22:56:38,193 dev_appserver.py:2884] "POST /_ah/upload/ahJkZXZ-cHJvdG8tc2NvaHNwcm9yGwsSFV9fQmxvYlVwbG9hZFNlc3Npb25fXxgTDA HTTP/1.1" 500 -

AppEngine 显然反对 HTTP 标头中的 unicode,但我没有做任何不寻常的 AFAIK。如果我进入 pdb 并查看 HTTPFound 对象,标题是:

ResponseHeaders([('Content-Type', 'text/html; charset=UTF-8'), ('Content-Length', '0'), ('Location', '/manager/swms')])

为什么我会从这些中得到一个 unicode 问题?

【问题讨论】:

    标签: python google-app-engine pyramid


    【解决方案1】:

    所以看起来您正在覆盖 appengine 支持的 webob,它是 2.7 runtime. 上的 1.1.1,并且金字塔 1.3 取决于 webob>=1.2。这很可能是问题所在,因为在 SDK 1.6.4 发布之前,是 Blobstore 处理程序将 sdk 保持在 webob==0.9 的状态。

    FWIW,预计 SDK 1.6.5(4 月下旬)将解决此问题。我知道这一点的唯一原因是,当 2.7 运行时被认为可以普遍使用时,我试图解决所有这些问题,但 SDK 不支持它。有关更多详细信息,请参阅此issue

    如果可能,我建议使用金字塔 1.2 运行它,我知道这在 appengine 上运行良好。并且只是推迟几周迁移到 1.3。 :)

    【讨论】:

    • 是的,由于 Pyramid 的依赖关系,我们正在使用 WebOb 1.2。我将问题追溯到提供 wsgi.url_scheme 作为 u'http' 的 WSGI 环境——这对我来说似乎很奇怪。 WebOb 的 response.py 使用它来创建标题(参见github.com/Pylons/webob/blob/master/webob/response.py 的第 1138 行),所以我只是将“返回 url”包装为“返回 str(url)”。有了这个,blob 可以很好地加载到数据存储(本地和生产)中,尽管我还没有尝试检索。 PS 上面,我认为你的意思是 >=1.2 而不是
    • FWIW,我已经在 GAE 上使用 Pyramid 1.3 向/从 Blobstore 上传和下载。我从 SDK 中获取了基于 webapp 的 Handler 对象,并对其进行了修改以与 Pyramid 视图可调用类一起使用。对于DownloadHandler,不需要提取字节范围,我取出了范围相关的代码。现在一切正常。
    【解决方案2】:

    又一个答案...添加 str() 解决了问题,但不是根本原因。我花了几个小时试图弄清楚为什么一个特定的重定向会引发此错误,而其他重定向却没有,然后才注意到错误重定向的 URL 缺少初始的“/”。

    我不知道为什么会出现这种情况 - 可能不完整的路径与完整路径的处理方式不同。但是,如果您遇到此错误,请尝试更改:

    self.redirect('home.view')
    

    到:

    self.redirect('/home.view')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-02
      • 1970-01-01
      • 2023-03-09
      • 2016-11-18
      • 2016-11-12
      • 2021-05-31
      • 2019-03-15
      • 1970-01-01
      相关资源
      最近更新 更多