Подтвердить что ты не робот

Отклик на конец колбы и продолжить обработку

Есть ли способ в Flask отправить ответ клиенту, а затем продолжить обработку? У меня есть несколько задач по ведению бухгалтерского учета, которые нужно выполнить, но я не хочу, чтобы клиент ожидал.

Обратите внимание, что это действительно очень быстрые вещи, которые я хочу сделать, создавая новый поток или используя очередь, здесь не очень уместно. (Одна из этих быстрых вещей фактически добавляет что-то в очередь заданий.)

4b9b3361

Ответ 2

Вы можете найти пример о том, как использовать сельдерей из флакона здесь https://gist.github.com/jzempel/3201722

Суть идеи (предназначенная для каламбура) состоит в том, чтобы определить длительные бухгалтерские задачи как @celery.task и использовать apply_async 1 или задержка с точки зрения для запуска задачи

Ответ 3

У меня была аналогичная проблема с моим блогом. Я хотел отправить уведомления по электронной почте тем, кто подписался на комментарии, когда был опубликован новый комментарий, но я не хотел, чтобы человек отправлял комментарий, ожидающий отправки всех писем, прежде чем он получит ответ.

Я использовал для этого multiprocessing.Pool. Я запустил пул одного рабочего (этого было достаточно, небольшой сайт трафика), а затем каждый раз, когда мне нужно отправить электронное письмо, я готовлю все в функции просмотра флагов, но передаю окончательный вызов send_email в пул через apply_async.

Ответ 4

Отказоустойчивые обратные вызовы не выполняются после того, как ответ был возвращен клиенту:

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()

При скручивании этого вы заметите задержку в 2 с до того, как появится ответ, а не завершающий скручивание, а затем журнал 2s позже. Это также подтверждается журналами:

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

Правильный способ выполнения после ответа возвращается использовать связующее ПО WSGI, которое добавляет привязку к методу закрытия итератора ответов. Это не так просто, как декоратор 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

Это резюме предыдущего ответа, приведенного здесь.