2015-12-21 418 views
5

我正在使用一個Flask Web服務器來提供一個耗時的計算接口。爲了提高性能,我想異步子進程使用flask-aiohttp

  1. 開始計算爲new subprocess能夠使用多個CPU內核的多個並行計算
  2. 讓計算運行的異步使用asyncio

要調用asyncio來自Flask的協程我開始使用flask-aiohttp,它很適合簡單的延遲任務,如示例中所示。 然而,我無法從內部瓶調用異步子:

#!/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'> 

我在做什麼錯?

+0

我相信你已經想通了,但* CALC_SCRIPT *做什麼?你正在用一個簡單的函數進行測試,比如一個階乘函數或其他東西? – wgwz

+0

這可能會有所幫助:http://stackoverflow.com/questions/24541192/python-asyncio-subprocess-never-finishes – wgwz

+0

是的,'CALC_SCRIPT'是一個[緩慢的斐波納契腳本](https://gitlab.com/snippets/11746)用於測試目的。我偶然發現了你已經鏈接到的問題,但我的[獨立版本](https://gitlab.com/snippets/11748)運行良好。 – Finwood

回答

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的情況下也能運行。