Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

python - What is the pythonic way of running an asyncio event loop forever?

From the docs it seems the recommended way to kickstart a asyncio application is to use asyncio.run(), so my application looks like this:

async def async_main():
    # Everything here can use asyncio.create_task():
    o = ObjectThatMustBeKeptReferenced()
    create_tasks_and_register_callbacks(o)

    # Wait forever, ugly:
    while True:
        await asyncio.sleep(10000)

asyncio.run(async_main())

This infinite loop at the end of async_main() feels very wrong. In other languages, there is where I would call the event loop forever. So I tried this:

def main():
    loop = asyncio.get_event_loop()

    # Everything here can use asyncio.create_task():
    o = ObjectThatMustBeKeptReferenced()
    create_tasks_and_register_callbacks(o)

    # Wait forever, pretty:
    loop.run_forever()

main()

The problem here is this will fail with an error of the sorts RuntimeError: no running event loop when I call asyncio.create_task() inside my functions, even though the event loop is created and registered on the thread.

What is the pythonic, one way of sleeping forever on the asyncio event loop?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can simply change the sleep loop to an ad-hoc event which is never set:

# wait forever
await asyncio.Event().wait()

If needed, you can easily modify this to store the event into a variable and propagate it as a shutdown signal.

Another option is for your function that creates the tasks to return the tasks it has created, in which case you can await them even though (or precisely because) they'll never complete:

async def async_main():
    o = ObjectThatMustBeKeptReferenced()
    tasks = create_tasks_and_register_callbacks(o)
    # wait forever, or until a task raises
    await asyncio.gather(*tasks)

While this doesn't communicate the intention of looping forever as clearly, it has the advantage that it will halt the program (and propagate the exception) if any of the tasks raises an unhandled exception.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...