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

查看:55
本文介绍了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.

推荐答案

长话短说,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() 来流式传输响应,如 this Stack Overflow answer to a similar question 建议.

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

通过流式传输,客户端确实在请求结束之前开始接收响应.但是,请求仍然是同步运行的,因此处理请求的 worker 一直很忙,直到流结束.

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 内置的 threadingmultiprocessing 以产生后台工作者.

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天全站免登陆