Python协程不与time.sleep()并发运行吗?

时间:2019-08-19 20:02:56

标签: python async-await coroutine python-asyncio

我正在尝试遵循https://docs.python.org/3/library/asyncio-task.html#coroutines上的示例;这是同时运行两个say_after协程的代码段:

import asyncio
import time


async def say_after(delay, what):
    await asyncio.sleep(delay)
    # time.sleep(delay)
    print(what)


async def main():
    task1 = asyncio.create_task(say_after(1, 'hello'))
    task2 = asyncio.create_task(say_after(2, 'world'))


    print(f"Started at {time.strftime('%X')}")

    await task1
    await task2

    print(f"Finished at {time.strftime('%X')}")


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

如果运行此命令,我会发现开始和结束相隔两秒:

Started at 12:59:35
hello
world
Finished at 12:59:37

但是,如果我将await asyncio.sleep(delay)替换为time.sleep(delay)(上面代码段中的注释行),我发现它们相距3秒,因此基本上是同步运行的:

Started at 13:00:53
hello
world
Finished at 13:00:56

我不太明白这一点;即使任务本身包含同步代码,让它们并行运行并发任务也没有意义吗?为什么此示例不再适用于time.sleep()而不是asyncio.sleep()

1 个答案:

答案 0 :(得分:2)

  

我不太明白这一点;即使任务本身包含同步代码,并没有使它们并行运行的要点?

并发!=并行性。在编写asyncio代码时,底层例程仍必须让流返回事件循环,以允许并发。无论如何,GIL仍然在那里。

  

为什么这个示例不再使用time.sleep()而不是asyncio.sleep()?

asyncio.sleep暂停当前任务,从而允许其他任务运行。 time.sleep不会,这是一个阻塞调用(“阻塞”表示它阻塞了主线程中的执行,并且使用asyncio的程序仍然是单线程的。)

协程提供合作并发,而不是并行性。

要通过协程实现良好的并发性,必须以非阻塞方式编写在asyncio.run中调用的任何代码。实际上,这意味着在任务中运行的任何代码都有责任发出信号,告知何时是暂停执行的适当时间,例如: “我没有做任何有用的事情,因为我正在等待I / O ...”-这允许另一个任务使用事件循环。