首页 > 解决方案 > 与 asyncio 一起运行阻塞和解除阻塞任务

问题描述

我想异步运行阻塞和解除阻塞任务。显然,有必要使用 run_in_executor 方法来阻止来自 asyncio 的任务。这是我的示例代码:

import asyncio
import concurrent.futures
import datetime
import time


def blocking():
    print("Enter to blocking()", datetime.datetime.now().time())
    time.sleep(2)
    print("Exited from blocking()", datetime.datetime.now().time())


async def waiter():
    print("Enter to waiter()", datetime.datetime.now().time())
    await asyncio.sleep(3)
    print("Exit from waiter()", datetime.datetime.now().time())


async def asynchronous(loop):
    print("Create tasks", datetime.datetime.now().time())
    task_1 = asyncio.create_task(waiter())

    executor = concurrent.futures.ThreadPoolExecutor(max_workers=3)
    task_2 = loop.run_in_executor(executor, blocking)

    tasks = [task_1, task_2]
    print("Tasks are created", datetime.datetime.now().time())
    await asyncio.wait(tasks)


if __name__ == "__main__":
    try:
        loop = asyncio.get_event_loop()
        loop.run_until_complete(asynchronous(loop))
    except (OSError) as exc:
        sys.exit('Exception: ' + str(exc))

我应该使用相同的事件循环来阻止 run_in_executor 中的任务,还是必须使用另一个?我应该在我的代码中进行哪些更改以使其异步工作?谢谢

标签: pythonasync-awaitpython-asyncio

解决方案


必须使用相同的循环。循环委托给执行程序,执行程序运行任务是事件循环的独立线程。所以你不必担心你的阻塞任务会阻塞事件循环。如果您使用单独的循环,则事件循环中的异步函数将无法等待阻塞在新循环中运行的函数的结果。

事件循环通过创建代表执行者任务的未来来管理这一点。然后它在其中一个执行器线程中运行阻塞任务,并且当执行器任务返回时,设置未来的结果并将控制返回到事件循环中的等待函数(如果有)。


推荐阅读