Flask 结束响应并继续处理 [英] Flask end response and continue processing

查看:19
本文介绍了Flask 结束响应并继续处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Flask 中有没有办法将响应发送给客户端,然后继续做一些处理?我有一些簿记任务要完成,但我不想让客户等待.

Is there a way in Flask to send the response to the client and then continue doing some processing? I have a few book-keeping tasks which are to be done, but I don't want to keep the client waiting.

请注意,这些实际上是我希望做的非常快的事情,因此创建新线程或使用队列在这里并不合适.(这些快速的事情之一实际上是向作业队列添加一些东西.)

Note that these are actually really fast things I wish to do, thus creating a new thread, or using a queue, isn't really appropriate here. (One of these fast things is actually adding something to a job queue.)

推荐答案

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

Sadly teardown callbacks do not execute after the response has been returned to the client:

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!
"

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

当卷曲这个时,你会注意到在响应显示之前有 2 秒的延迟,而不是卷曲立即结束,然后在 2 秒后记录.日志进一步证实了这一点:

When curling this you'll note a 2s delay before the response displays, rather than the curl ending immediately and then a log 2s later. This is further confirmed by the logs:

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

返回响应后执行的正确方法是使用 WSGI 中间件,该中间件为 响应迭代器的关闭方法.这不像 teardown_request 装饰器那么简单,但它仍然非常简单:

The correct way to execute after a response is returned is to use WSGI middleware that adds a hook to the close method of the response iterator. This is not quite as simple as the teardown_request decorator, but it's still pretty straight-forward:

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

然后你可以像这样使用:

Which you can then use like this:

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

从 shell 中,您将看到响应立即返回,然后在 2 秒后 after_response 将命中日志:

From the shell you will see the response return immediately and then 2 seconds later the after_response will hit the logs:

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

这是在此处.

这篇关于Flask 结束响应并继续处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆