从 Flask 请求启动新的子进程

Posted

技术标签:

【中文标题】从 Flask 请求启动新的子进程【英文标题】:Starting new subproces from a Flask request 【发布时间】:2013-01-14 07:01:29 【问题描述】:

我有一个请求来自一个用@app.route('/url/path/to/view') 修饰的函数。

它会做一些事情来查找一些数据并进行一些计算,并且在此期间该函数正常运行。但是,最后我想启动一个新进程(从 python 函数,当前使用multiprocessing.Process)。一旦这个进程启动,我希望函数返回,而新进程继续独立运行。

我当前方法的伪代码

def start_process(arguments):
    # some code here that the process will run

p = multiprocessing.Process(target=start_process, args=(...))
p.start()

return app.response(" 'status': 'ok' ", mimetype='application/json')

这种方法是否有效,Flask 应用程序能否在不影响新进程的情况下继续运行?

【问题讨论】:

我建议改用任务队列(如Celery),它更适合运行后台作业。 虽然不使用 Celery,但我认为这将是我正在采用的方法。我将保存我需要的信息以备后用并进行批处理。 【参考方案1】:

使用多进程启动子进程是完全可以接受的。这是一个使用多处理在后台更新数据库的最小工作示例。正如 Audrius 所说,最终你可能会想要一个合适的task queue。

from flask import Flask, jsonify
import multiprocessing
import dataset
import time
import random

app = Flask(__name__)
DATABASE_URL = 'sqlite:///dev.db'

def add_person(name):
    """ Add a person to the db. """
    person = 'name': name, 'age': -1, 'status': 'processing'
    db = dataset.connect(DATABASE_URL)
    db['people'].insert(person)
    return True

def update_person(name):
    """ Update a person in db with a fake long running process 
    that guesses a random age. """
    time.sleep(10)  # simulate a long running process
    age = random.randint(1, 120)
    person = 'name': name, 'age': age, 'status': 'finished'
    db = dataset.connect(DATABASE_URL)
    db['people'].update(person, ['name'])
    return True

def get_person(name):
    """ Retrieve a person from the db. """
    db = dataset.connect(DATABASE_URL)
    person = db['people'].find_one(name=name)
    return person

@app.route('/<name>')
def index(name):
    """ Get person. If name not found, add_person to db and start update_person. """
    if not get_person(name):
        add_person(name)
        thread = multiprocessing.Process(target=update_person, args=(name,))
        thread.start()
    person = get_person(name)
    return jsonify(person)

if __name__ == '__main__':
    app.run(debug=True)

在子进程运行时访问localhost:5000/bert


    "status": "processing",
    "age": -1,
    "name": "bert",
    "id": 1

等待,然后刷新,您会看到子进程已完成:


    "status": "finished",
    "age": 28,
    "name": "bert",
    "id": 1

【讨论】:

以上是关于从 Flask 请求启动新的子进程的主要内容,如果未能解决你的问题,请参考以下文章

golang 热重启

Linux学习-进程管理

创建一个不是创建进程子进程的新进程

Apache的三种工作模式及相关配置

关于wait 和 exit

Shell脚本入门 07:进程与信号