立即从同步代码执行异步回调

时间:2019-05-23 08:06:59

标签: python python-asyncio python-3.7 threadpoolexecutor

问题

我有一个目前不支持异步的库,需要从异步代码中调用。异步代码通过处理程序(以下代码中的handler函数)调用库。执行处理程序时,库会定期调用回调(callback_wrapper)以报告进度。

同步处理程序在ThreadPoolExecutor中执行,以便主事件循环能够在处理程序运行时处理其他事件。

发生的事情是立即执行同步回调,但是异步回调仅在主处理程序执行后执行。理想的结果是立即执行异步回调。

我猜事件循环在run_in_executor调用中被阻止,但是我不确定如何解决。

代码

import asyncio
import time
from concurrent.futures.thread import ThreadPoolExecutor

loop = asyncio.get_event_loop()


def handler():
    print('handler started')
    callback_wrapper()
    time.sleep(1)
    print('handler stopped')


async def callback():
    print('callback')


def callback_wrapper():
    print('callback wrapper started')
    asyncio.ensure_future(callback(), loop=loop)
    print('callback wrapper stopped')


async def main():
    handler()


with ThreadPoolExecutor() as pool:
    async def thread_handler():
        await loop.run_in_executor(pool, handler)


    loop.run_until_complete(main())

输出

handler started
callback wrapper started
callback wrapper stopped
handler stopped
callback

所需的输出

handler started
callback wrapper started
callback
callback wrapper stopped
handler stopped

1 个答案:

答案 0 :(得分:1)

由于@ user4815162342的输入,我提出了以下解决方案:

import asyncio
import time
from concurrent.futures.thread import ThreadPoolExecutor

loop = asyncio.get_event_loop()


def handler():
    print('handler started')
    callback_wrapper()
    time.sleep(1)
    print('handler stopped')


async def callback():
    print('callback')


def callback_wrapper():
    print('callback wrapper started')
    asyncio.run_coroutine_threadsafe(callback(), loop).result()
    print('callback wrapper stopped')


async def main():
    await thread_handler()


with ThreadPoolExecutor() as pool:
    async def thread_handler():
        await loop.run_in_executor(pool, handler)


    loop.run_until_complete(main())

产生预期结果:

handler started
callback wrapper started
callback
callback wrapper stopped
handler stopped