3

This is a follow up question to this question:

Why do most asyncio examples use loop.run_until_complete()?

I'm trying to figure out how asynchronous programming work in python. There's something very basic which I'm still not sure about..

when having this line code: asyncio.ensure_future(someTask) , will this line ALONE actually enqueue the Future returned in the default event loop and start the task? Or do I ALSO need to call loop.run_until_complete(someTask) (or some other kind of run) before that in order to get the event loop up and running?

CodeMonkey
  • 11,196
  • 30
  • 112
  • 203

2 Answers2

4

asyncio.ensure_future(someTask) will this line ALONE actually enqueue the Future returned in the default event loop and start the task?

It will schedule the coroutine, but it won’t run it. You still need to run the loop to do that. You can do that with

loop.run_forever()

If you want the loop to run until someTask is done rather than forever, use

future = asyncio.ensure_future(someTask)
loop.run_until_complete(future)

Don’t call both asyncio.ensure_future(someTask) and loop.run_until_complete(someTask) or you’ll end up with a RuntimeError since someTask will have already been scheduled.

dirn
  • 19,454
  • 5
  • 69
  • 74
  • 1
    then why do we need to write `asyncio.ensure_future(someTask)` instead of `loop.run_until_complete(someTask)`? – Emerson Xu Dec 18 '19 at 09:00
0

when having this line code: asyncio.ensure_future(someTask), will this line ALONE actually enqueue the Future returned in the default event loop and start the task?

That depends on when the line is executed. If it executes from some coroutine while the event loop is running, then you truly don't need to do anything else - the task will appear to magically run "in the background".

If the event loop isn't running yet, then you need to spin up the event loop for any task to run, not just the freshly added one. loop.run_until_complete(some_specific_task) is just one option, other is loop.run_forever(), meaning "run the event loop until someone calls loop.stop()".

Note that ensure_future(task) is a no-op because if you already have a Task, it will just be returned unchanged. ensure_future(some_coroutine()) will wrap the coroutine into a Task, schedule it in the event loop, and return it, effectively calling loop.create_task() for you. When the argument is known to be a coroutine, it is recommended to call create_task directly.

user4815162342
  • 141,790
  • 18
  • 296
  • 355