Rob Truxal
Rob Truxal

Reputation: 6408

How to terminate a python asyncio event_loop when all tasks have completed

Ok so basically I need clarification RE: how to use the asyncio.run_until_complete(Future) function.

After adding 3 tasks to my loop I attempt to create a Future"done callback" using the asyncio.wait() function.

In the following code, my event_loop.close() never gets run:

import asyncio

async def repeat_message(message, interval_seconds, max_iters=10):
    iters = 0
    while True:
        print(message)
        if iters >= max_iters:
            return 'Complete.'
        iters += 1
        await asyncio.sleep(interval_seconds)

if __name__ == "__main__":
    message_A = "xXxXxXxXxXxXxXxXxXxXx"
    interval_A = 0.5
    message_B = "I LOVE"
    interval_B = 1
    message_C = "EXPLOSIONS!"
    interval_C = 1.5

    event_loop = asyncio.get_event_loop()

    task_A = event_loop.create_task(repeat_message(message_A, interval_A))
    task_B = event_loop.create_task(repeat_message(message_B, interval_B))
    task_C = event_loop.create_task(repeat_message(message_C, interval_C))

    completed = event_loop.create_future()
    completed.add_done_callback(asyncio.wait([task_A, task_B, task_C], loop=event_loop))
    try:
        event_loop.run_until_complete(completed)
    finally:
        event_loop.close()
    # Never prints.
    print('DONE')

Upvotes: 2

Views: 1868

Answers (1)

Rob Napier
Rob Napier

Reputation: 299265

This is what gather is for. Get rid of your completed future, and use gather this way:

event_loop.run_until_complete(asyncio.gather(task_A, task_B, task_C))

What you've written here creates a Future and configures it so that when the future completes, then it will wait for the tasks. But you never complete the future (with set_result() for instance). Future isn't really about running things asynchronously. It's just a data structure that represents "some future value that will be provided by someone eventually calling set_result() or raising an exception with set_exception()." That turns out to often be useful for asynchronous work, but it isn't itself a coroutine.

Upvotes: 4

Related Questions