traductor science route meaning app python flask

python - science - Respuesta final del matraz y continuar el procesamiento.



flask translate (4)

Lamentablemente, las devoluciones de llamada de desmontaje no se ejecutan después de que la respuesta se haya devuelto al cliente:

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

Al hacer esto, notará un retraso de 2 segundos antes de que se muestre la respuesta, en lugar de que el rizo finalice inmediatamente y luego un registro de 2 segundos más tarde. Esto se confirma aún más por los registros:

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

La forma correcta de ejecutar después de que se devuelve una respuesta es usar middleware WSGI que agrega un enlace al método de cierre del iterador de respuesta . Esto no es tan simple como el decorador teardown_request , pero sigue siendo bastante sencillo:

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

Que luego puedes usar así:

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

Desde el shell verá que la respuesta regresa inmediatamente y luego 2 segundos después, after_response llegará a los registros:

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

Este es un resumen de una respuesta anterior proporcionada here .

¿Hay alguna forma en Flask de enviar la respuesta al cliente y luego continuar procesando? Tengo algunas tareas de contabilidad que están por hacer, pero no quiero hacer esperar al cliente.

Tenga en cuenta que estas son cosas realmente rápidas que deseo hacer, por lo que crear un nuevo hilo, o usar una cola, no es realmente apropiado aquí. (Una de estas cosas rápidas es en realidad agregar algo a la cola de trabajo).


Puede encontrar un ejemplo sobre cómo usar el apio desde Flask aquí https://gist.github.com/jzempel/3201722

La esencia de la idea (juego de palabras intencionado) es definir las tareas largas de contabilidad como @ celery.task y usar apply_async 1 o retrasar desde dentro de la vista para iniciar la tarea



Tuve un problema similar con mi blog. Quería enviar correos electrónicos de notificación a aquellos suscritos a los comentarios cuando se publicaba un nuevo comentario, pero no quería que la persona que publicaba el comentario estuviera a la espera de que se enviaran todos los correos electrónicos antes de recibir su respuesta.

Utilicé un multiprocessing.Pool . multiprocessing.Pool para esto. Comencé un grupo de un trabajador (que era suficiente, sitio de poco tráfico) y luego cada vez que necesito enviar un correo electrónico, preparo todo en la función de vista del Frasco, pero paso la llamada final send_email al grupo a través de apply_async .