Don P
Don P

Reputation: 63718

In Python, kick off an async function and return early

I have a function in python that should kick off an asynchronous 'slow' function, and return before that 'slow' function completes.

async def doSomethingSlowButReturnQuickly():
  asyncio.create_task(_mySlowFunction())

  return "Returning early! Slow function is still running."

async def _mySlowFunction():
  // Do some really slow stuff that isn't blocking for our other function.

Running this still seems to cause the 'return' to not happen until AFTER my async task has completed.

How do I correct this?

(And apologies, this is day #2 writing Python)

Upvotes: 1

Views: 2185

Answers (2)

SystemSigma_
SystemSigma_

Reputation: 1435

Maybe it's a dull answer, but if you want to stick with asyncio, I would advise to be sure using await in everyasync def functions.


async def doSomethingSlowButReturnQuickly(): 
    task = asyncio.create_task(_mySlowFunction())

    # must await something here!

    return "Returning early! Slow function is still running."

async def _mySlowFunction():

    # must await something here

If you don't need to get the slow function return value, why don't you directly call the two coroutines from a main function?

import asyncio 

async def doSomethingSlowButReturnQuickly(): 

    await asyncio.sleep(0.1) # must await something here! 

    return "Returning early! Slow function is still running."

async def _mySlowFunction():

    await asyncio.sleep(10) # must await something here

async def main():
    tasks = [_mySlowFunction(), doSomethingSlowButReturnQuickly()]
    asyncio.gather(*tasks)

asyncio.run(main())

Upvotes: 1

VoidTwo
VoidTwo

Reputation: 637

This isn't exactly what you asked, but you can run code in an async executor and continue while it is still running:

from concurrent.futures import ThreadPoolExecutor
from time import sleep


def blocking_code():
    sleep(2)
    print('inner')
    return 'result'


def main():
    with ThreadPoolExecutor(max_workers=1) as executor:
        future = executor.submit(blocking_code)
        print('after')
        print(future.result())
    return


if __name__ == '__main__':
    main()

Output:

after
inner
result

Upvotes: 2

Related Questions