Is it possible to take a blocking function such as work
and have it run concurrently in a ProcessPoolExecutor
that has more than one worker?
The problem is in the producer
. Instead of allowing the jobs to run in the background, it waits for each job to finish, thus serializing them. If you rewrite producer
to look like this (and leave consumer
unchanged), you get the expected 1s duration:
async def producer():
for i in range(num_jobs):
fut = loop.run_in_executor(executor, work)
fut.add_done_callback(lambda f: queue.put_nowait(f.result()))
await loop.run_in_executor(executor, work)
blocks the loop until work
completes, as a result you only have one function running at a time.
To run jobs concurrently, you could use asyncio.as_completed
:
async def producer():
tasks = [loop.run_in_executor(executor, work) for _ in range(num_jobs)]
for f in asyncio.as_completed(tasks, loop=loop):
results = await f
await queue.put(results)