Reputation: 11520
I was trying to explain an example of async programming in python but I failed. Here is my code.
import asyncio
import time
async def asyncfoo(t):
time.sleep(t)
print("asyncFoo")
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncfoo(10)) # I think Here is the problem
print("Foo")
loop.close()
My expectation is that I would see:
Foo
asyncFoo
With a wait of 10s before asyncFoo
was displayed.
But instead I got nothing for 10s, and then they both displayed.
What am I doing wrong, and how can I explain it?
Upvotes: 5
Views: 5478
Reputation: 4954
Your expectation would work in contexts where you run your coroutine as a Task
independent of the flow of the code. Another situation where it would work is if you are running multiple coroutines
side-by-side, in which case the event-loop will juggle the code execution from await
to await
statement.
Within the context of your example, you can achieve your anticipated behaviour by wrapping your coroutine in a Task object, which will continue-on in the background without holding up the remainder of the code in the code-block from whence it is called.
For example.
import asyncio
async def asyncfoo(t):
await asyncio.sleep(t)
print("asyncFoo")
async def my_app(t):
my_task = asyncio.ensure_future(asyncfoo(t))
print("Foo")
await asyncio.wait([my_task])
loop = asyncio.get_event_loop()
loop.run_until_complete(my_app(10))
loop.close()
Note that you should use asyncio.sleep()
instead of the time
module.
Upvotes: 2
Reputation: 30472
run_until_complete
will block until asyncfoo
is done. Instead, you would need two coroutines executed in the loop. Use asyncio.gather
to easily start more than one coroutine with run_until_complete
.
Here is a an example:
import asyncio
async def async_foo():
print("asyncFoo1")
await asyncio.sleep(3)
print("asyncFoo2")
async def async_bar():
print("asyncBar1")
await asyncio.sleep(1)
print("asyncBar2")
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(async_foo(), async_bar()))
loop.close()
Upvotes: 11
Reputation: 1484
run_until_complete
is blocking. So, even if it'll happen in 10 seconds, it will wait for it. After it's completed, the other print occurs.
You should launch your loop.run_until_complete(asyncfoo(10))
in a thread or a subprocess if you want the "Foo" to be print before.
Upvotes: -1