在烧瓶中返回立即响应,但在新线程中完成处理



我有一个从10秒起的过程,但是在10秒后,我不需要将信息返回给用户,而是将其写入DynamoDB,这就是为什么我想要用户不必等待10秒。相反,我希望在发布请求后立即做出"成功"响应。

我读了几篇文章,在这篇文章中,答案是带有拆卸回调的,但没有一个例子。

我阅读了这篇文章,但这对我的问题无济于事。

我当然阅读了拆除票和这种模式,但我不知道如何以另一种方式使用它。

我的代码看起来像这样:

@app.route('/ocr/read_image', methods=['POST'])
def get_text():    
    return jsonify('Success')
@app.teardown_request
def teardown_request(response):        
    time.sleep(10)

它实际上返回了"成功"消息,但在10秒之后。

有没有办法在10秒之前返回"成功"消息?

我一直在读到芹菜可能是可能的,但是如果可以的话,我很乐意避免它。

有人知道该怎么做吗?

螺纹在这里不必要地复杂化事物。为了在不引入线程的情况下执行您想要做的事情,您可以将WSGI响应关闭方法挂钩。最简单的方法是使用werkzeug闭合器助手。

import traceback
from werkzeug.wsgi import ClosingIterator
class AfterThisResponse:
    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 extensioe
        app.after_this_response = self
        # install middleware
        app.wsgi_app = AfterThisResponseMiddleware(app.wsgi_app, self)
    def flush(self):
        try:
            for fn in self.callbacks:
                try:
                    fn()
                except Exception:
                    traceback.print_exc()
        finally:
            self.callbacks = []
class AfterThisResponseMiddleware:
    def __init__(self, application, after_this_response_ext):
        self.application = application
        self.after_this_response_ext = after_this_response_ext
    def __call__(self, environ, start_response):
        iterator = self.application(environ, start_response)
        try:
            return ClosingIterator(iterator, [self.after_this_response_ext.flush])
        except Exception:
            traceback.print_exc()
            return iterator

您然后使用这样的扩展名:

import flask
import time
app = flask.Flask("after_response")
AfterThisResponse(app)
@app.route("/")
def home():
    @app.after_this_response
    def post_process():
        time.sleep(2)
        print("after_response")
    return "Success!n"

当您卷曲时,您会看到立即的成功,然后在日志后面2s,您会看到您的" after_response"消息:

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

此解决方案是根据我的答案改编的摘要:

  • 在返回烧瓶中的响应后,需要执行功能
  • 烧瓶结束响应并继续处理
  • 烧瓶返回响应后执行功能

正如Ardaglio所说,最好的方法是使用多线程。

我没有使用芹菜,因为我认为这很复杂,而且我的问题很容易。

所以,我正在使用线程:

from threading import Thread
@app.route('/ocr/read_image', methods=['POST'])
def get_text():    
    Thread(target=continue_processing).start()
    return jsonify('Success')
def continue_processing():
    time.sleep(10)
    print('Hi')

但是,您必须小心。我正在使用带有TensorFlow的Keras作为后端,如果您使用它,那么您将有一个不错的值错误ValueError: Tensor Tensor()is not an element of this graph.

因此,要避免在线程中避免使用,您可以在制作模型后保存图:

GRAPH = tf.get_default_graph()

,然后您可以在这种方式中使用它在异步过程中:

with GRAPH.as_default():
    do something with your model 

希望可以帮助某人。

芹菜可以完成您的工作。

您需要执行一些异步过程。这是您想要的确切意思:致电"某人"处理您的信息,然后在不等待已处理的信息返回的情况下将消息发送给您的用户/应用程序。

然后,您可以添加一个回调以通知其他方法。

所有可以用芹菜或兔子。

最新更新