How to block and wait the result of an async function in a non-async function?

Viewed 900

Very simple code:

async def poll():
    await asyncio.sleep(1)

def caller(somefunction):
    somefunction() # we don't know if callable is async or not

def main():
    caller(poll) # how to pass an async function "poll" here?

I want to call "poll" by passing it as a callable/lambda to "caller" function. Normally, in a well designed language, e.g. C# you'd do poll().Result because poll() returns a Task which has methods like Wait() and Result to block and wait OR you can use "await" if you want to block and wait AND return to the caller of the current async method you're in.

1 Answers

When declaring a async function and then calling it, also requires to wait for it. Like with the await asyncio.sleep(1), you need to await the callee(). See below:

import asyncio

async def callee():
    await asyncio.sleep(1)
    print ("first")
    return 1


async def caller():
    await callee() # how do I wait the result of this?
    print("second")


async def main():
    await caller()    


if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())

--EDIT--

To run a coroutine you have 3 options in asyncio.

  1. The asyncio.run() function: which can't be used here because there can only be 1 event loop run at the same time.
  2. await the coroutine: which you don't want/can't in a sync function
  3. With asyncio.create_task(): which needs to be awaited too somewhere in your code

When you dont't await option 2 and 3, the coroutine simply won't execute. So what you are trying to do here can't be achieved with the asyncio package.

What I don't really understand is why you want to execute an async function to wait for it in sync? That defeats the purpose of using tasks..

Related