Home > database >  running async code within a function which contains blocking code
running async code within a function which contains blocking code

Time:11-10

import asyncio
import time


def blocking_function():
    print("Blocking function called")
    time.sleep(5)
    print("Blocking function finished")


async def concurrent_function():
    for x in range(10):
        print(x)
        await asyncio.sleep(1)


async def main():
    print("Main function called")
    loop = asyncio.get_event_loop()
    loop.run_in_executor(None, blocking_function)
    await concurrent_function()
    print("Main function finished")

if __name__ == "__main__":
    asyncio.run(main())

When attempting to run a blocking function while asyncio code is also running, this works perfectly. However, if I have a funciton which contains blocking code (eg. a libary which is not asyncronous I am unable to do this) Because the function contains both blocking code, and asynconrous code I cannot use run in executor. How can I get around this?

The below code unfortunetly errors due to the blocking_function not being awaited, but you annot use that in conjunction with run_in_executor

async def blocking_function():
    for x in range(4):
        print("Blocking function called")
        time.sleep(1)
        print("Blocking function finished")
        print("Async code running:")
        await asyncio.sleep(1)
        print("Async code finished")


async def concurrent_function():
    for x in range(10):
        print(x)
        await asyncio.sleep(1)

async def main():
    print("Main function called")
    loop = asyncio.get_event_loop()
    loop.run_in_executor(None, blocking_function)
    await concurrent_function()
    print("Main function finished")

if __name__ == "__main__":
    asyncio.run(main())

CodePudding user response:

just create an event loop in the second thread and run the async function there.

import asyncio
import time

async def blocking_function():
    for x in range(4):
        print("Blocking function called")
        time.sleep(1)
        print("Blocking function finished")
        print("Async code running:")
        await asyncio.sleep(1)
        print("Async code finished")

def async_blocking_function_runner(func):
    # creates another event loop in the other thread and runs func in it
    res = asyncio.run(func())
    return res


async def concurrent_function():
    for x in range(10):
        print(x)
        await asyncio.sleep(1)


async def main():
    print("Main function called")
    loop = asyncio.get_event_loop()
    res = loop.run_in_executor(None, async_blocking_function_runner, blocking_function)
    await concurrent_function()
    await res  # make sure the task in second thread is done
    print("Main function finished")

if __name__ == "__main__":
    asyncio.run(main())
  • Related