烧瓶结束响应并继续处理 [英] Flask end response and continue processing
问题描述
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!\n"
if __name__ == "__main__":
app.run()
卷曲时,您会注意到在显示响应之前有2s的延迟,而不是卷曲立即结束,然后在2s之后记录.日志进一步确认了这一点:
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
这是在此处.
这篇关于烧瓶结束响应并继续处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!