Rahul
Rahul

Reputation: 11520

How to use async/await in python 3.5+

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

Answers (3)

songololo
songololo

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

Udi
Udi

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

iFlo
iFlo

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

Related Questions