烧瓶应用与背景线程

San*_*San 17 multithreading flask

我正在创建一个烧瓶应用程序,对于一个请求,我需要运行一些长时间运行的作业,这不需要在UI上等待.我将创建一个线程并向UI发送消息.该线程将计算并更新数据库.但是,UI会在提交时看到一条消息.下面是我的实现,但它正在运行线程,然后将输出发送到UI,这不是我喜欢的.如何在后台运行此线程?

@app.route('/someJob')
def index():
    t1 = threading.Thread(target=long_running_job)
    t1.start()
    return 'Scheduled a job'

def long_running_job
    #some long running processing here
Run Code Online (Sandbox Code Playgroud)

如何让线程t1运行后台并立即发送消息?

Den*_*hko 54

试试这个例子,在Python 3.4.3/Flask 0.11.1上测试

from flask import Flask
from time import sleep
from concurrent.futures import ThreadPoolExecutor

# DOCS https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor
executor = ThreadPoolExecutor(2)

app = Flask(__name__)


@app.route('/jobs')
def run_jobs():
    executor.submit(some_long_task1)
    executor.submit(some_long_task2, 'hello', 123)
    return 'Two jobs was launched in background!'


def some_long_task1():
    print("Task #1 started!")
    sleep(10)
    print("Task #1 is done!")


def some_long_task2(arg1, arg2):
    print("Task #2 started with args: %s %s!" % (arg1, arg2))
    sleep(5)
    print("Task #2 is done!")


if __name__ == '__main__':
    app.run()
Run Code Online (Sandbox Code Playgroud)

  • 好答案。为我工作。 (2认同)
  • @arshpreet我有几乎相同的代码在生产中工作,从2016年到现在通过uWSGI运行没有任何问题.使用Gunicorn进行测试也很好. (2认同)
  • 如果你想在 Flask 中使用 concurrent.futures,请查看 [Flask-Executor](https://github.com/dchevell/flask-executor)。它提供了一种在 Flask 中初始化执行器的更惯用的方法,并提供了一些方便的功能(保留应用程序上下文、应用程序工厂模式支持、装饰器) (2认同)
  • 如果 `some_long_task1` 或 `some_long_task2` 引发异常怎么办?我写过类似的代码,但我发现异常被抑制了。 (2认同)

Dyl*_*ony 18

查看Flask-Executor,它在后台使用 concurrent.futures,让您的生活变得非常轻松。

from flask_executor import Executor

executor = Executor(app)

@app.route('/someJob')
def index():
    executor.submit(long_running_job)
    return 'Scheduled a job'

def long_running_job
    #some long running processing here
Run Code Online (Sandbox Code Playgroud)

这不仅在后台运行作业,而且使他们可以访问应用程序上下文。它还提供了一种存储作业的方法,以便用户可以重新登录以获取状态。


rde*_*ges 5

最好的办法是使用消息代理。python 世界中有一些优秀的软件就是为了做到这一点:

两者都是极好的选择。

按照您的方式生成线程几乎从来都不是一个好主意,因为这可能会导致处理传入请求等问题。

如果您查看 celery 或 RQ 入门指南,它们会引导您以正确的方式完成此操作!

  • 是的,我知道 celery 和 redis 队列。但是,我正在尝试将它们作为一个简单的线程后台作业。不确定,如果我使用线程会弹出什么问题。你可以解释吗。另外,如果我想按照我编码的方式工作,我需要什么改变?根本不可能吗? (7认同)