使用Flask进行异步后台处理?

时间:2018-11-06 23:33:46

标签: python python-3.x flask python-asyncio

我有一个要通过http端点调用的进程,它将触发异步进程(几乎是批处理之类的。)

没有服务器功能,我的代码:

async def run(cmd):
    proc = await asyncio.create_subprocess_shell(
        cmd,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

    stdout, stderr = await proc.communicate()

    print(f'[{cmd!r} exited with {proc.returncode}]')
    if stdout:
        if proc.returncode == 0:
            print(f'[stdout]\n{Fore.GREEN}{stdout.decode()}{Style.RESET_ALL}!')
        else:
            print(f'[stdout]\n{Fore.RED}{stdout.decode()}{Style.RESET_ALL}!')
    if stderr:
        print(f'[stderr]\n{Fore.RED}{stderr.decode()}{Style.RESET_ALL}!')

然后我可以通过以下方式调用子流程:

async def abar():
    await asyncio.gather(
        run('python3 --version') #literally ANY long process
       #that i need to call
    )

我可以从那里做

  

asyncio.run(abar())

,我的应用程序成功运行。我的目标是将asyncio.run部分放在烧瓶端点后面:

@app.route("/batch")
def e2e():
    asyncio.run(abar())
    return 'OK'

但是,这样做似乎会引发错误:

  

无法添加子处理程序,子监视程序未附加循环

通过某个HTTP端点触发异步子流程调用的最佳方法是什么?

我尝试使用subprocess.call,但这似乎并不异步...

1 个答案:

答案 0 :(得分:0)

我能够使用subprocess.Popen

解决此问题

代替

async def abar():
    await asyncio.gather(
        run('python3 --version') #literally ANY long process
       #that i need to call
    )

我做到了:

async def abar():
   Popen(['pyton3', '--version']) # or any long process

以及实际的烧瓶路径中:

@app.route("/batch")
    def e2e():
       abar()