I have a long_task
function which runs a heavy cpu-bound calculation and I want to make it asynchronous by using the new asyncio framework. The resulting long_task_async
function uses a ProcessPoolExecutor
to offload work to a different process to not be constrained by the GIL.
The trouble is that for some reason the concurrent.futures.Future
instance returned from ProcessPoolExecutor.submit
when yielded from throws a TypeError
. Is this by design? Are those futures not compatible with asyncio.Future
class? What would be a workaround?
I also noticed that generators are not picklable so submitting a couroutine to the ProcessPoolExecutor
is going to fail. Is there any clean solution to this as well?
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())