Python 在 Flask 中返回响应后需要执行一个函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18082683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Need to execute a function after returning the response in Flask
提问by naga4ce
For one request alone i need to execute a function after sending the response to the client. Because the function takes time and that ends up in connection timeout Socket error: [Errno 32] Broken pipe
对于一个请求,我需要在向客户端发送响应后执行一个函数。因为该函数需要时间并且以连接超时而告终Socket error: [Errno 32] Broken pipe
Is there a way in Flaskto execute function after returning the request
Flask有没有办法在 返回请求后执行函数
回答by codegeek
You can use the after_request decorator or customize to create a after_this_request which only works for that particular request.
您可以使用 after_request 装饰器或自定义来创建仅适用于该特定请求的 after_this_request。
Take a look at this snippet http://flask.pocoo.org/snippets/53/
回答by tbicr
You can try use streaming. See next example:
您可以尝试使用流式传输。见下一个例子:
import time
from flask import Flask, Response
app = Flask(__name__)
@app.route('/')
def main():
return '''<div>start</div>
<script>
var xhr = new XMLHttpRequest();
xhr.open('GET', '/test', true);
xhr.onreadystatechange = function(e) {
var div = document.createElement('div');
div.innerHTML = '' + this.readyState + ':' + this.responseText;
document.body.appendChild(div);
};
xhr.send();
</script>
'''
@app.route('/test')
def test():
def generate():
app.logger.info('request started')
for i in range(5):
time.sleep(1)
yield str(i)
app.logger.info('request finished')
yield ''
return Response(generate(), mimetype='text/plain')
if __name__ == '__main__':
app.run('0.0.0.0', 8080, True)
All magic in this example in genarator where you can start response data, after do some staff and yield empty data to end your stream.
此示例中的所有魔术都在生成器中,您可以在其中开始响应数据,然后执行一些工作人员并产生空数据以结束您的流。
For ditails look at http://flask.pocoo.org/docs/patterns/streaming/.
回答by Brandon Wang
There is no Flask-native way to accomplish this. after_request
will still run beforereturning the response to the client, not after.
没有 Flask 原生的方式来实现这一点。after_request
仍将在将响应返回给客户端之前运行,而不是之后。
回答by Matthew Story
A more general solution than the flask iterator solution is to write a WSGI middleware that adds a callback to the response closemethod. Here we use the werkzeug ClosingIteratorhelper and a flask app extension to achieve this:
比烧瓶迭代器解决方案更通用的解决方案是编写一个 WSGI 中间件,为响应关闭方法添加回调。在这里,我们使用了 werkzeug ClosingIterator助手和一个Flask应用程序扩展来实现这一点:
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, after_response):
iterator = self.application(environ, after_response)
try:
return ClosingIterator(iterator, [self.after_response_ext.flush])
except Exception:
traceback.print_exc()
return iterator
You can then use your after_response
decorator like this:
然后你可以after_response
像这样使用你的装饰器:
import flask
import time
app = flask.Flask("after_response")
AfterResponse(app)
@app.after_response
def after():
time.sleep(2)
print("after_response")
@app.route("/")
def home():
return "Success!\n"
When you curl this, you'll see that it responds immediately and curl closes, then 2s later your "after" message appears in the logs:
当您 curl 时,您会看到它立即响应并关闭 curl,然后 2 秒后您的“之后”消息出现在日志中:
127.0.0.1 - - [25/Jun/2018 15:41:51] "GET / HTTP/1.1" 200 -
after_response
回答by Alekos
I will expose my solution.
我将公开我的解决方案。
You can use threads to compute anything after returned something in your function called by a flask route.
在由烧瓶路由调用的函数中返回某些内容后,您可以使用线程来计算任何内容。
import time
from threading import Thread
from flask import request, Flask
app = Flask(__name__)
class Compute(Thread):
def __init__(self, request):
Thread.__init__(self)
self.request = request
def run(self):
print("start")
time.sleep(5)
print(self.request)
print("done")
@app.route('/myfunc', methods=["GET", "POST"])
def myfunc():
thread_a = Compute(request.__copy__())
thread_a.start()
return "Processing in background", 200