当前位置: 首页 > 面试题库 >

烧瓶结束响应并继续处理

郏经纬
2023-03-14
问题内容

Flask中是否可以将响应发送给客户端,然后继续进行某些处理?我要完成一些簿记任务,但是我不想让客户等待。

请注意,这些实际上是我想做的非常快的事情,因此在这里实际上不适合创建新线程或使用队列。(这些快速的操作之一实际上是在作业队列中添加一些内容。)


问题答案:

可悲的是,将响应返回给客户端后,拆卸回调不执行:

import flask
import time
app = flask.Flask("after_response")

@app.teardown_request
def teardown(request):
    time.sleep(2)
    print("teardown_request")

@app.route("/")
def home():
    return "Success!\n"

if __name__ == "__main__":
    app.run()

卷曲时,您会注意到在显示响应之前有2s的延迟,而不是卷曲立即结束,然后在2s之后记录。日志进一步确认了这一点:

teardown_request
127.0.0.1 - - [25/Jun/2018 15:41:51] "GET / HTTP/1.1" 200 -

返回响应后执行的正确方法是使用WSGI中间件,该中间件向响应迭代器的close方法添加了一个钩子。这不像teardown_request装饰器那么简单,但是仍然很简单:

import traceback
from werkzeug.wsgi import ClosingIterator

class AfterResponse:
    def __init__(self, app=None):
        self.callbacks = []
        if app:
            self.init_app(app)

    def __call__(self, callback):
        self.callbacks.append(callback)
        return callback

    def init_app(self, app):
        # install extension
        app.after_response = self

        # install middleware
        app.wsgi_app = AfterResponseMiddleware(app.wsgi_app, self)

    def flush(self): for fn in self.callbacks:
            try:
                fn()
            except Exception:
                traceback.print_exc()

class AfterResponseMiddleware:
    def __init__(self, application, after_response_ext):
        self.application = application
        self.after_response_ext = after_response_ext

    def __call__(self, environ, start_response):
        iterator = self.application(environ, start_response)
        try:
            return ClosingIterator(iterator, [self.after_response_ext.flush])
        except Exception:
            traceback.print_exc()
            return iterator

然后可以这样使用:

@app.after_response
def after():
    time.sleep(2)
    print("after_response")

从外壳程序中,您将看到响应立即返回,然后2秒钟后after_response它将返回日志:

127.0.0.1 - - [25/Jun/2018 15:41:51] "GET / HTTP/1.1" 200 -
after_response

这是此处提供的先前答案的摘要。



 类似资料:
  • 我已经用flask在python上制作了一个restapi(端口:5000),我正在从一个网站(端口:80)发出get和post请求。我收到了cors错误,所以我尝试在RESTAPI中为站点创建一个响应头。但是我得到了导入错误: 我已经下载了烧瓶cors模块并升级它,并确保它是在正确的路径,但它仍然不工作。 API代码:

  • 我正在检索mongo集合中与子字符串查询匹配的所有文档: 然后将所有匹配的文档作为JSONArray返回给java客户端: 当我想在java端解析JSONArray时,我必须执行以下操作: 我很有信心我在这里做错了什么。我不必先将JSONArray元素转换为字符串,然后再转换为JSONObject。我是否可以直接从JSONArray中检索JSONObject,而不用先将其转换为字符串?

  • 我有一个烧瓶应用程序,我正试图过渡到通过gunicorn运行。我在这方面遇到了很多问题。以下是我的应用程序的运行代码: 首先,如果DEBUG_FLAG==true,应用程序将永远不会真正启动,但会继续重新启动,在本地点击它将不起作用。它只是一次又一次地这样做: 如果我用DEBUG_FLAG==False启动它,它实际上会启动并服务于一些请求,但由于未知原因,它仍然会频繁中断并重新启动: 如前所述,

  • 问题内容: 我已经使用jQuery和AJAX几周了,并且在调用完成后,我看到了两种“继续”脚本的不同方式:和。 从jQuery文档的提要中,我们得到: .done():说明:添加要解析Deferred对象时要调用的处理程序。 成功:(。ajax()选项):如果请求成功,则要调用的函数。 因此,在AJAX调用完成/解决之后,两者都要做一些事情。我可以随机使用其中之一吗?有什么区别?何时使用一种替代另

  • 问题内容: 例如,此URL: 应该返回一个MIME类型的响应。我有两个静态图像, 如果type为1,则应返回,否则返回。在烧瓶中怎么做? 问题答案: 您使用类似 发送回或,具体取决于类型查询参数。有关更多信息,请参见函数和对象的文档。

  • 这是我的代码: 但是,当我从浏览器向服务器发出请求时,会出现以下错误: 我也尝试过这种方法,在请求之后设置响应头: 没有骰子。我得到同样的错误。有没有办法只在路由函数中设置响应头?像这样的东西是理想的: 但是我无论如何也找不到这样做。请帮忙。 编辑 如果我卷曲的url与POST请求这样: 我得到的答复是: 有什么想法吗?