使用 flask-aiohttp 的异步子进程

Posted

技术标签:

【中文标题】使用 flask-aiohttp 的异步子进程【英文标题】:asynchronous subprocess using flask-aiohttp 【发布时间】:2015-12-21 10:24:35 【问题描述】:

我正在使用Flask Web 服务器来为耗时的计算提供接口。为了提高性能,我想

    以new subprocess 开始计算,以便能够使用多个 CPU 内核进行多个并发计算 使用asyncio 让计算异步运行

为了从 Flask 调用 asyncio 协程,我开始使用 flask-aiohttp,它非常适用于简单的延迟任务,如示例中所示。 但是,我无法从 Flask 内部调用异步子进程:

#!/usr/bin/env python3
# coding: utf-8

from flask import Flask
from flask.ext.aiohttp import AioHTTP, async

import asyncio
from asyncio.subprocess import PIPE

CALC_SCRIPT = './calc'

app = Flask(__name__)
aio = AioHTTP(app)

@app.route('/calc/<int:n>')
@async
def calc(n):
    print('calc() called'.format(n))
    create = asyncio.create_subprocess_exec(CALC_SCRIPT, str(n),
                                            stdout=PIPE, stderr=PIPE)
    print('create... ', end='')
    process = yield from create
    print('process created. !r, type='.format(process,
                                                  type(process)))
    yield from process.wait()
    print('process finished.')

    # yields (stdout, stderr)
    result = '\n'.join(ch.decode().rstrip() for ch in
                        (yield from process.communicate()) if ch)
    return result

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

进程正在创建,但永远不会返回:

GET http://127.0.0.1:5000/calc/5
calc(5) called
creating... process created. <Process 5647>,
    type=<class 'asyncio.subprocess.Process'>

我做错了什么?

【问题讨论】:

我相信你已经考虑过了,但是 CALC_SCRIPT 是做什么的呢?您是否使用简单的函数进行测试,例如阶乘之类的? 这可能会有所帮助:***.com/questions/24541192/… 是的,CALC_SCRIPT 是用于测试目的的slow fibonacci script。我偶然发现了您链接到的那个问题,但我的 standalone version 运行良好。 process.wait() 是否会导致计算通过?您可以在视图函数之外创建一个asyncio.couroutine,然后在视图函数中以与独立版本类似的方式调用它吗? 【参考方案1】:

原因:从子线程运行 asyncio 子进程有限制,请参阅 asyncio 文档Subprocess and threads。

详细信息:使用debug=True,Flask-aiohttp 在由 Werkzeug 的run_with_reloader 启动的子线程中处理请求。关闭调试,您的代码将正常运行。

或者根据上面的文档,Flask-aiohttp 应该在调用run_with_reloader 之前添加对asyncio.get_child_watcher() 的调用。通过此调用,即使使用 debug=True,您的代码也会运行。

【讨论】:

以上是关于使用 flask-aiohttp 的异步子进程的主要内容,如果未能解决你的问题,请参考以下文章

Linux学习-进程管理

golang 热重启

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

关于wait 和 exit

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

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