2012-09-25 49 views
40

瓶破裂的管道,我想烧瓶中的应用程序发送一个本地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导致整个烧瓶应用程序冻结。当我发送一个杀手信号时,我得到一个破损的管道错误。有没有办法防止烧瓶在这里冻结?

回答

89

在一个能够处理并发请求的正确的WSGI服务器(可能是gunicornuWSGI)下运行你的烧瓶应用程序,它会工作。在开发,能够在瓶提供的服务器线程:

app.run(threaded=True) 

但要注意,不建议在生产中使用的瓶服务器。

会发生什么事是,使用你是一个请求您的水壶的应用程序,但由于它仍忙于处理第一个,也不会以第二次请求,直到它与第一个请求响应完成请求。

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

+0

+1,绝对))><(( –

+2

我运行螺纹WSGI应用程序,但我得到断裂的管道反正: app.run(调试=真,螺纹=真,主机='0.0。 0.0',port = 8080) – loretoparisi

+1

@loretoparisi:没有无法诊断的细节。用你的'app.run()'行运行代码并调整'curl'命令可以正常工作。也许你应该发布一个新的 –

16

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

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

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

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

+0

+1在请求处理程序中提出请求在大多数情况下是不好的,对自己发出http请求... ick –

+0

我遇到了问题,因为我合并了两个Web服务这是以前作为独立流程运行的唯一交互这两种Web服务之间的关系就是POST。我使用蓝图和繁荣将它们结合到了同一个过程中,它冻结了。所以,更多的重构是为了。 – jfocht

+0

@Corbin那么threaded = True选项与TwistedWeb不足以满足多处理和每个请求的多线程执行? – loretoparisi

3

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

从烧瓶中的changelog:

  • 将其还原为行为改变是做而不是返回内部服务器错误(pull请求#2006)开发服务器崩溃。
+0

是的!谢谢你的提示。升级到烧瓶0.12修复了这个问题。现在只需记录这些错误而不会导致我的服务器崩溃。 –