I'm working on migrating a Python 3 codebase from complete sync to partially asyncio. The reason it is partial is because the part of the service that read messages is not compatible with asyncio, yet so it has to remain something like this: for message in read_messages(): handle_message(message) I'm converting handle_message to handle_message_async which is defined as async function and everything inside of it will be asyncio compatible. For now I want to continue handle messages one by one and be able to use asyncio inside the handling of a single message. My question is what is the difference between those two options: asyncio.run for message in read_messages(): asyncio.run(handle_message_async(message)) asyncio.Runner() with asyncio.Runner() as async_runner: for message in read_messages(): async_runner.run(handle_message_async(message)) Is there a difference in term of setup and teardown that maybe happening in asyncio.run? Is there a difference in how exceptions will be raised back to the sync part of the code? Continue reading...