0
votes

As we know, inside an async function, code will not continue executing until the awaited coroutine finishes executing:

await coro()
# or
await asyncio.gather(coro_1(), coro_2())

# Code below will run AFTER the coroutines above finish running = desired effect

Outside (or inside) an async function it is possible to add coroutines to an event loop with asyncio.create_task(coro()), which returns a Task object.

In my scenario the tasks are added to an >>> existing running loop <<<, and the code that follows will continue executing without waiting for that task/coroutine to finish. Of course, it is possible to execute a callback function when the task finishes with task_obj.add_done_callback(callback_func).

asyncio.create_task(coro()) is especially useful on Jupyter Notebooks / Jupyter Lab because Jupyter runs an event loop in the background. Calling asyncio.get_event_loop() will retrieve Jupyter's event loop. Inside a Jupyter Notebook we cannot call asyncio.run(coro()) or loop.run_until_complete() because the loop is already running (except if we run the async code an a separate process and create a new event loop inside that process, but this is not the use case I'm looking for).

So my question is how can I await (from outside an async function = without using await keyword) on an asyncio task (or group of tasks) to finish and retrieve results before executing the code that follows?

tsk_obj = asyncio.create_task(coro())   # adds task to a (in my case) running event loop

# QUESTION:
# What can be done to await the result before executing the rest of the code below?

print('Result is:', tsk_obj.result())
#  ^-- this of course will execute immediately  = NOT the desired effect
#      (the coroutine is very likely still running on the event loop and the result is not ready)
1

1 Answers

1
votes

Without concurrent execution this is logically impossible. To wait for something outside an async function means to block the current thread. But if the current thread is blocked the task cannot possibly run. You can actually write such code (waiting on a threading.Event object, for example, which is set at the end of your task). But the program will deadlock for the reason I gave.