带有要求的烧瓶破碎管

时间:2012-09-25 22:04:36

标签: python ubuntu python-2.7 flask

我想在一个烧瓶应用程序中发送一个本地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会导致整个烧瓶应用冻结。当我发送一个kill信号时,我的管道出现故障。有没有办法防止烧瓶在这里冻结?

4 个答案:

答案 0 :(得分:106)

在能够处理并发请求的适当WSGI服务器(可能是gunicornuWSGI)下运行您的烧瓶应用程序,它将起作用。在开发时,使用以下命令启用Flask提供的服务器中的线程:

app.run(threaded=True)

但请注意,不建议将Flask服务器用于生产。从Flask 1.0开始,默认情况下会启用threaded,并且您确实希望在命令行上使用flask命令来运行您的应用。

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

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

答案 1 :(得分:19)

这里有几件事情,我会尝试一次一个地解决这些问题。

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

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

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

答案 2 :(得分:5)

导致崩溃的错误是fixed in Version 0.12,于2016年12月21日发布。是的!这是许多人一直在等待的重要修复。

来自Flask更改日志:

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

答案 3 :(得分:0)

我在发布方法上遇到了同样的问题, 总的来说,我的帖子方法什么都不做, 那就是为什么这个问题来了

return _socket.socket.send(self._sock, data, flags) urllib3.exceptions.ProtocolError:
('Connection aborted.', BrokenPipeError(32, 'Broken pipe'))

if request.method == 'POST':
    print(len(request.data))
return 'dummy'

这个print起到了作用