烧瓶与请求断开的pipe道

我想在烧瓶应用程序中发送本地REST请求,如下所示:

from flask import Flask, url_for, request import requests app = Flask(__name__) @app.route("/<name>/hi", methods=["POST"]) def hi_person(name): form = {"name": name} return requests.post(url_for("hi", _external=True), data=form) @app.route("/hi", methods=["POST"]) def hi(): return 'Hi, %s!' % request.form["name"] 

发送curl -X POST http://localhost:5000/john/hi会导致整个烧瓶应用程序冻结。 当我发送一个杀手信号,我得到一个坏的pipe道错误。 有没有办法防止烧瓶在这里冻结?

运行你的烧瓶应用程序在一个适当的WSGI服务器能够处理并发请求(也许gunicorn或uWSGI ),它会工作。 在开发过程中,在Flask提供的服务器中启用线程:

 app.run(threaded=True) 

但请注意,Flask服务器不推荐用于生产用途。

会发生什么情况是,使用请求,您正在向烧瓶应用程序发出第二个请求,但是由于它仍然忙于处理第一个请求,因此在第一个请求完成之前,它不会响应第二个请求。

顺便提一下,在Python 3下,socketserver实现更为优雅地处理断开连接,并继续服务而不是崩溃。

这里有几件事情,我会尝试一次性解决它们。

首先,你可能使用玩具开发服务器。 这台服务器有很多限制, 主要是这些限制是一次只能处理一个请求。 在第一次请求期间创build第二个请求时,您正在locking您的应用程序: requests.post()函数正在等待Flask响应,但Flask本身正在等待post()返回! 解决此特定问题的方法是在multithreading或多进程环境中运行WSGI应用程序。 我更喜欢http://twistedmatrix.com/trac/wiki/TwistedWeb ,但还有其他几个选项。

有了这个…这是一个反模式。 您几乎肯定不想调用HTTP请求的所有开销,只是为了在两个视图之间共享某些function。 正确的做法是重构一个独立的函数来完成共享工作。 我不能真正重构你的具体例子,因为你所拥有的非常简单,甚至不值得两个观点。 你想要build立什么?

编辑:评论问玩具stdlib服务器中的multithreading模式是否足以防止发生死锁。 我要说“也许”。 是的,如果没有任何依赖使两个线程都不能进行,并且两个线程都有足够的进度来完成他们的networking任务,那么请求就会正确地完成。 但是,确定两个线程是否会相互死锁是不可判定的(certificate省略为钝),我不能肯定地说stdlib服务器可以正确执行。

导致崩溃的错误已 2016年12月21日发布的版本0.12中得到修复 。是的! 这是很多人一直在等待的一个重要的解决scheme。

从瓶更换日志:

  • 还原导致dev服务器崩溃而不是返回内部服务器错误(拉请求#2006)的行为更改。