-1

I have read When will/won't Python suspend execution of a coroutine?, the accepted anwser mentions:

It is worth mentioning that asyncio.sleep is explicitly guaranteed to suspend execution and defer to the event loop, even when the specified delay is 0 (in which case it will immediately resume on the next event loop pass)."

From python doc https://docs.python.org/3/library/asyncio-dev.html#concurrency-and-multithreading:

When a Task executes an await expression, the running Task gets suspended, and the event loop executes the next Task.

But in my following example, it didn't suspend when it meet await asyncio.sleep(0.1) in do_something, What is the problem of my understanding?

import asyncio

async def do_something(i):
    await asyncio.sleep(0.1)
    print('in do_something')
    

async def main():
    for i in range(10):
        print(i)
        await do_something(i)


t1 = time.time()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
print('cost time:', time.time() - t1)

expected output:

0
1
2
3
4
5
6
7
8
9
in do_something
in do_something
in do_something
in do_something
in do_something
in do_something
in do_something
in do_something
in do_something
in do_something
cost time: 1.0283539295196533

Real output:

in do_something
1
in do_something
2
in do_something
3
in do_something
4
in do_something
5
in do_something
6
in do_something
7
in do_something
8
in do_something
9
in do_something
cost time: 1.0283539295196533
user4815162342
  • 141,790
  • 18
  • 296
  • 355
fitz
  • 540
  • 4
  • 11
  • 3
    `do_something` awaits `sleep`, and `main` awaits `do_something`. The loop in `main` won't continue until `do_something` completes which completes when `sleep` completes. As long as you `await do_something`, it's basically all synchronous execution. – deceze Jul 05 '21 at 06:55
  • @deceze Thanks for your help, I mistakenly think this is an asynchronous call. – fitz Jul 05 '21 at 07:13
  • 4
    It *is* an asynchronous call, in the sense that the control is passed to the event loop during the sleep, and it would execute other tasks - if there were any. For example, if you change `loop.run_until_complete(main())` to `loop.run_until_complete(asyncio.gather(main(), main()))`, you will observe that the two mains are executed in parallel. As the doc says, `await` means "call this async function, and suspend me until it's finished". So "await" means "wait", and if you only have one task, the wait will make it look like everything is sync. – user4815162342 Jul 05 '21 at 12:46
  • 1
    You can change `await do_something(i)` to `asyncio.create_task(do_something(i))`, and add an `await asyncio.sleep(10)` at the end of `main` (to prevent the program from finishing), and you should see your expected output. – user4815162342 Jul 05 '21 at 12:47
  • @user4815162342 Thanks, this is a clear answer! – fitz Jul 05 '21 at 13:04
  • I've now posted it as an answer. – user4815162342 Jul 05 '21 at 14:34

1 Answers1

0

But in my following example, it didn't suspend when it meet await asyncio.sleep(0.1) in do_something

It did suspend, in the sense that the control was passed to the event loop during the sleep, allowing it to execute other tasks - if there had been any. To see that, change loop.run_until_complete(main()) to loop.run_until_complete(asyncio.gather(main(), main())), and you'll observe that the two mains are executed in parallel.

As the docs say, await means "call this async function, and suspend me until it's finished". So "await" implies "wait", and if you only have one task, the wait will make it look like everything is sync. You can change await do_something(i) to asyncio.create_task(do_something(i)), and add an await asyncio.sleep(10) at the end of main (to prevent the program from finishing), and you should see your expected output.

user4815162342
  • 141,790
  • 18
  • 296
  • 355