Issue
I read the following code
async def f():
sc_client = session.client("ec2")
for id in ids:
await IOLoop.current().run_in_executor(None, lambda: client.terminate(id))
How does it compare to the following code? Will client.terminate
be run in parallel? But each execution is awaited?
for id in ids:
client.terminate(id)
Solution
Will client.terminate be run in parallel?
NO, it still runs as sequence.
IOLoop.current().run_in_executor
will run the blocking function
in a separate thread and returns an asyncio.Future
, while await
will wait until the Future
which call client.terminate
finish, then the loop continue.
The difference the 2 options you given is:
If the program has other coroutine to run, using the 1st option, the other coroutine won't block, while using the 2nd option, the other coroutine will block to wait your for loop finish.
An example to make you understand it (Here, will use loop.run_in_executor
to simulate the IOLoop.current().run_in_executor
for simple sake):
test.py:
import asyncio
import concurrent.futures
import time
def client_terminate(id):
print(f"start terminate {id}")
time.sleep(5)
print(f"end terminate {id}")
async def f():
loop = asyncio.get_running_loop()
for id in range(2):
with concurrent.futures.ThreadPoolExecutor() as pool:
await loop.run_in_executor(pool, client_terminate, id)
# client_terminate(id)
async def f2():
await asyncio.sleep(1)
print("other task")
async def main():
await asyncio.gather(*[f(), f2()])
asyncio.run(main())
The run output is:
$ python3 test.py
start terminate 0
other task
end terminate 0
start terminate 1
end terminate 1
You could see the two client_terminate
in for loop still runs in sequence, BUT, the function f2
which print other task
inject between them, it won't block asyncio scheduler
to schedule f2
.
Additional:
If you comment the 2 lines related to await loop.run_in_executor
& threadpool
, directly call client_terminate(id)
, the output will be:
$ python3 test.py
start terminate 0
end terminate 0
start terminate 1
end terminate 1
other task
Means if you don't wraps the blocking function
in a Future
, the other task
will have to wait your for loop
to finish which waste CPU.
Answered By - atline
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.