12

重い CPU バウンドの計算を実行するlong_task関数があり、新しい asyncio フレームワークを使用して非同期にしたいと考えています。結果のlong_task_async関数はProcessPoolExecutor、GIL によって制約されないように作業を別のプロセスにオフロードするために a を使用します。

問題は、何らかの理由でconcurrent.futures.Futurefrom から返されたときに返されたインスタンスProcessPoolExecutor.submitが をスローすることTypeErrorです。これは設計によるものですか?asyncio.Futureそれらの先物はクラスと互換性がありませんか? 回避策は何ですか?

また、ジェネレーターはピクル化できないため、クルーチンを に送信するProcessPoolExecutorと失敗することにも気付きました。これにもきれいな解決策はありますか?

import asyncio
from concurrent.futures import ProcessPoolExecutor

@asyncio.coroutine
def long_task():
    yield from asyncio.sleep(4)
    return "completed"

@asyncio.coroutine
def long_task_async():
    with ProcessPoolExecutor(1) as ex:
        return (yield from ex.submit(long_task)) #TypeError: 'Future' object is not iterable
                                                 # long_task is a generator, can't be pickled

loop = asyncio.get_event_loop()

@asyncio.coroutine
def main():
    n = yield from long_task_async()
    print( n )

loop.run_until_complete(main())
4

2 に答える 2

12

loop.run_in_executorエグゼキューターを使用しますconcurrent.futuresが、戻り値をasyncio未来にマップします。

元のasyncioPEPは、いつかメソッドを成長させて、それを使用できるようにすることを示唆して いますが、今のところ、ライブラリはサポートのみを必要とするように設計されており、それ以上のものは必要ありません。(そうしないと、3.3 で実際に動作しないコードもあります。)concurrent.futures.Future__iter__yield fromyield from

于 2014-03-17T00:39:27.880 に答える
12

を呼び出して aconcurrent.futures.Futureを anにラップできます。以下のコードで試してみました。正常に動作しますasyncio.futureasyncio.wrap_future(Future)

from asyncio import coroutine
import asyncio
from concurrent import futures


def do_something():
    ls = []
    for i in range(1, 1000000):
        if i % 133333 == 0:
            ls.append(i)
    return ls


@coroutine
def method():
    with futures.ProcessPoolExecutor(max_workers=10) as executor:
        job = executor.submit(do_something)
        return (yield from asyncio.wrap_future(job))

@coroutine
def call_method():
    result = yield from method()
    print(result)


def main():
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(call_method())
    finally:
        loop.close()


if __name__ == '__main__':
    main()
于 2015-07-25T06:02:22.773 に答える