首页 > 解决方案 > 可视化 asyncio 协程执行

问题描述

我试图了解异步协程是如何从头到尾执行的。可以说我有这个功能

async def statemachine(state):

执行以下操作:

  1. 读取远程服务器上的值
  2. 写入远程mysql服务器
  3. 写入本地redis服务器
  4. 从远程 mysql 服务器中删除一条记录
  5. 创建事件并通知协程执行完成

由于 async 暂停执行以给其他协程时间执行,因此执行是否总是从第 1 步开始到第 5 步。

标签: python-3.xpython-asyncio

解决方案


协程总是按顺序执行。然而,许多(协同)例程可以(协同)一起操作,同时受到事件循环或各种调度程序的监督。

因此,如果您将所有任务堆叠在一个协程中,例如:

async def statemachine(state):
    await read_value_on_remote_server()
    await write_to_remote_mysql_server()
    await write_to_local_redis_server()
    await delete_a_record_from_a_remote_mysql_server()
    await create_event_and_notify_coroutine_execution_has_finished()

statemachine将一一等待每项任务,直到它们完成。这种情况并没有真正有用,并且与同步代码相比没有任何好处。

异步执行大放异彩的场景是,假设您有一个 Web 应用程序,它statemachine为每个用户请求安排一个协程。现在,每当用户通过请求访问您的服务器时,都会在事件循环中安排一个新的协程。而且因为事件循环一次只能运行一件事(伪并发),它会让每个协程执行(假设使用循环算法)直到它们挂起,因为它们正在等待一个对象或另一个协程等待另一个对象。

协程挂起的方式是使用 await 语句。这让事件循环知道协程正在等待一个不一定受 CPU 限制的操作。例如网络调用或用户输入。

值得庆幸的是,我们不知道事件循环的实现细节以及它如何设法知道何时应该恢复协程。这通常使用 Python 的 stdlib select https://docs.python.org/2/library/select.html之类的库来完成。

对于大多数用例,您应该知道协程始终按顺序执行,并且事件循环是通过使用协作方法来管理协程执行的(例如,与典型的 OS 调度程序不同)。

如果你想伪并发运行几个协程,你可以看看asycio.gather或更正确的asyncio.create_task. 希望这可以帮助。


推荐阅读