Flask返回响应后执行函数 [英] Execute a function after Flask returns response

查看:1264
本文介绍了Flask返回响应后执行函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Flask返回响应之后,我有一些代码需要执行 .我认为为它设置像Celery这样的任务队列不够复杂.关键要求是Flask必须在运行此功能之前将响应返回给客户端.它等不及要执行该功能.

I have some code that needs to execute after Flask returns a response. I don't think it's complex enough to set up a task queue like Celery for it. The key requirement is that Flask must return the response to the client before running this function. It can't wait for the function to execute.

对此存在一些疑问,但是似乎没有答案能解决在将响应发送给客户端之后运行任务,它们仍然同步执行,然后返回响应的情况.

There are some existing questions about this, but none of the answers seem to address running a task after the response is sent to the client, they still execute synchronously and then the response is returned.

  • Need to execute a function after returning the response in Flask
  • Python Flask sending response immediately
  • Need to execute a function after returning the response in Flask
  • Flask end response and continue processing

推荐答案

长话短说,Flask没有提供任何特殊功能来完成此任务.对于简单的一次性任务,请考虑使用Python的多线程,如下所示.对于更复杂的配置,请使用RQ或Celery之类的任务队列.

The long story short is that Flask does not provide any special capabilities to accomplish this. For simple one-off tasks, consider Python's multithreading as shown below. For more complex configurations, use a task queue like RQ or Celery.

重要的是要了解Flask提供的功能以及为什么它们不能实现预期的目标.所有这些都在其他情况下很有用,并且很好阅读,但对后台任务没有帮助.

It's important to understand the functions Flask provides and why they do not accomplish the intended goal. All of these are useful in other cases and are good reading, but don't help with background tasks.

Flask的after_request处理程序,如此模式用于延迟的请求回调和根据每个请求附加不同功能的代码段,会将请求传递给回调函数.预期的用例是修改请求,例如附加cookie.

Flask's after_request handler, as detailed in this pattern for deferred request callbacks and this snippet on attaching different functions per request, will pass the request to the callback function. The intended use case is to modify the request, such as to attach a cookie.

因此,请求将等待这些处理程序完成执行,因为期望结果是请求本身将发生更改.

Thus the request will wait around for these handlers to finish executing because the expectation is that the request itself will change as a result.

这类似于after_request,但是teardown_request没有收到request对象.这样就意味着它不会等待请求,对吧?

This is similar to after_request, but teardown_request doesn't receive the request object. So that means it won't wait for the request, right?

这似乎是解决方案,如针对类似堆栈溢出问题的答案所建议.并且由于Flask的文档解释了拆解回调与实际请求无关并且没有收到请求上下文,那么您就有充分的理由相信这一点.

This seems like the solution, as this answer to a similar Stack Overflow question suggests. And since Flask's documentation explains that teardown callbacks are independent of the actual request and do not receive the request context, you'd have good reason to believe this.

不幸的是,teardown_request仍然是同步的,它只是在Flask的请求处理的后期发生,而该请求不再可修改. Flask 在返回响应之前仍将等待拆卸功能完成,例如此Flask回调和错误列表规定.

Unfortunately, teardown_request is still synchronous, it just happens at a later part of Flask's request handling when the request is no longer modifiable. Flask will still wait for teardown functions to complete before returning the response, as this list of Flask callbacks and errors dictates.

Flask可以通过将生成器传递给Response()来流式传输响应,如

Flask can stream responses by passing a generator to Response(), as this Stack Overflow answer to a similar question suggests.

通过流式传输,客户端确实在请求结束之前就开始接收响应.但是,请求仍然是同步运行的,因此处理请求的工作人员很忙,直到流完成为止.

With streaming, the client does begin receiving the response before the request concludes. However, the request still runs synchronously, so the worker handling the request is busy until the stream is finished.

用于流式传输的Flask模式包括有关使用stream_with_context()的一些文档必须包含请求上下文.

This Flask pattern for streaming includes some documentation on using stream_with_context(), which is necessary to include the request context.

Flask不提供在后台运行功能的解决方案,因为这不是Flask的责任.

Flask doesn't offer a solution to run functions in the background because this isn't Flask's responsibility.

在大多数情况下,解决此问题的最佳方法是使用任务队列,例如RQ或Celery.这些为您管理诸如配置,计划和分配工作人员之类的棘手事情,这是此类问题最常见的答案,因为它是最正确的,并迫使您以考虑上下文的​​方式进行设置等.正确.

In most cases, the best way to solve this problem is to use a task queue such as RQ or Celery. These manage tricky things like configuration, scheduling, and distributing workers for you.This is the most common answer to this type of question because it is the most correct, and forces you to set things up in a way where you consider context, etc. correctly.

如果您需要在后台运行一个函数并且不想建立一个队列来管理它,则可以使用Python内置的

If you need to run a function in the background and don't want to set up a queue to manage this, you can use Python's built in threading or multiprocessing to spawn a background worker.

您无法从后台任务访问request或Flask的其他线程本地变量,因为该请求在该位置不会处于活动状态.而是在创建数据时将所需的数据从视图传递到后台线程.

You can't access request or others of Flask's thread locals from background tasks, since the request will not be active there. Instead, pass the data you need from the view to the background thread when you create it.

@app.route('/start_task')
def start_task():
    def do_work(value):
        # do something that takes a long time
        import time
        time.sleep(value)

    thread = Thread(target=do_work, kwargs={'value': request.args.get('value', 20)})
    thread.start()
    return 'started'

这篇关于Flask返回响应后执行函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆