【问题标题】:Flask crashes with ValueError: too many values to unpackFlask 因 ValueError 崩溃:太多值无法解包
【发布时间】:2013-05-18 21:01:48
【问题描述】:

我有一个烧瓶应用程序,它与另一个网络服务通信。我有这个错误,似乎只有当两个应用程序都在同一台服务器上运行时才会发生,但我不知道来源是什么。 Flask 应用程序通过 Apache 中的 WSGIScriptAlias 托管在 /tools

[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114] mod_wsgi (pid=25705): Exception occurred processing WSGI script '/opt/tools-frontend/wsgi.py'.
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114] Traceback (most recent call last):
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]   File "/opt/tools-frontend/ENV_1/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]     return self.wsgi_app(environ, start_response)
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]   File "/opt/tools-frontend/ENV_1/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]     response = self.make_response(self.handle_exception(e))
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]   File "/opt/tools-frontend/ENV_1/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]     response = self.full_dispatch_request()
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]   File "/opt/tools-frontend/ENV_1/lib/python2.7/site-packages/flask/app.py", line 1361, in full_dispatch_request
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]     response = self.make_response(rv)
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]   File "/opt/tools-frontend/ENV_1/lib/python2.7/site-packages/flask/app.py", line 1447, in make_response
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]     rv = self.response_class(rv, headers=headers, status=status)
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]   File "/opt/tools-frontend/ENV_1/lib/python2.7/site-packages/werkzeug/wrappers.py", line 627, in __init__
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]     self.headers = Headers(headers)
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]   File "/opt/tools-frontend/ENV_1/lib/python2.7/site-packages/werkzeug/datastructures.py", line 836, in __init__
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]     self.extend(defaults)
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]   File "/opt/tools-frontend/ENV_1/lib/python2.7/site-packages/werkzeug/datastructures.py", line 978, in extend
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114]     for key, value in iterable:
[Thu May 23 13:11:44 2013] [error] [client 41.164.8.114] ValueError: too many values to unpack
[Thu May 23 13:11:44 2013] [debug] mod_deflate.c(615): [client 41.164.8.114] Zlib: Compressed 590 to 372 : URL /tools/api/login/, referer: http://www.website.com/tools

API 托管在同一台机器上的不同域中,查看日志文件,它工作正常。

API 调用在以下函数中进行:

@app.route('/api/', methods=['GET', 'POST', 'PUT', 'DELETE'])
@app.route('/api/<path:endpoint>', methods=['GET', 'POST', 'PUT', 'DELETE'])
def api(endpoint=None):
    # extract POST/PUT variables
    dat = request.form
    if len(dat) == 0:
        # extract GET variables
        dat = request.args
    # submit request to API
    out = call_api(request.method, endpoint, dat, request.files)
    return out

调用:

def call_api(method, endpoint, data=None, files=None):
    url = 'https://api.example.com' + endpoint
    if method.upper() == "GET":
        r = requests.get(url, data=data, verify=False)
    # ... similarly for other verbs  
    return r.text, r.status_code, r.headers

【问题讨论】:

  • 您是否要在视图中设置标题?你能分享一下代码吗? headers 的值不是 None,也不是 dict,而是可迭代的。 Iterable 应该产生 (key, value) 对,但这不是它得到的。
  • 在我看来,当flask/werkzeug 试图处理响应时,崩溃正在发生。您可以在堆栈跟踪中看到我的代码根本没有涉及,顶部文件是flask/app/py。触发 API 调用的行是 r = requests.get(url, data=data, verify=False)
  • 你能分享你的视图代码吗?解析响应的标头令人窒息,您的代码不在堆栈跟踪中,因为错误不在您的视图中,是的,但这并不意味着它不是原因 - 毕竟它会生成响应。

标签: python flask mod-wsgi wsgi werkzeug


【解决方案1】:

我最好的猜测是您返回一个特殊的标题字典(来自 python-requests)而不是普通的。 Flask 采用两种形式的标题:

{'key': 'value'}
# and
[('key', 'value')]

由于您的特殊 dict 未被识别为真正的 dict,它将被视为元组列表,这将失败。

改变

return r.text, r.status_code, r.headers

return r.text, r.status_code, r.headers.items()

【讨论】:

  • 我不可能对此进行足够的投票!你解决了一周的痛苦和挫折。
猜你喜欢
  • 2019-03-28
  • 2019-01-25
  • 2020-01-20
  • 1970-01-01
  • 1970-01-01
  • 2015-12-20
  • 2016-02-02
  • 1970-01-01
相关资源
最近更新 更多