asyncio模块是怎么工作的,为什么我更新的sample是运行同步的?

How does the asyncio module work, why is my updated sample running synchronously?

我已经在 Python 3.6 中为 asyncio 尝试了以下代码: 示例 1:

import asyncio
import time

async def hello():

    print('hello')
    await asyncio.sleep(1)
    print('hello again')

tasks=[hello(),hello()]    
loop=asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

输出符合预期:

hello
hello
hello again
hello again

然后我想把asyncio.sleep改成另一个def:

async def sleep():
    time.sleep(1)

async def hello():

    print('hello')
    await sleep()
    print('hello again')


tasks=[hello(),hello()]    
loop=asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

输出:

hello
hello again
hello
hello again

好像不是运行异步模式,而是正常的同步模式

问题是:为什么它不是 运行 异步模式,我怎样才能将旧的同步模块更改为 'async' 同步模块?

Asyncio 使用了一个事件循环,它会选择队列中的任务(一个独立的协程调用链)接下来要激活。事件循环可以就什么任务准备好进行实际工作做出明智的决定。这就是事件循环还负责 creating connections and watching file descriptors 和其他 I/O 原语的原因;它让事件循环深入了解何时有 I/O 操作正在进行或何时可以处理结果。

无论何时使用 await,都有机会 return 控制循环,然后循环可以将控制权传递给另一个任务。然后选择执行哪个任务取决于具体的实现; asyncio 参考实现 offers multiple choices, but there are other implementations, such as the very, very efficient uvloop implementation.

您的示例仍然是异步的。碰巧的是,通过将 await.sleep() 替换为同步 time.sleep() 调用,在一个新的协程函数中,您将 2 个协程引入了不会产生的任务调用链,从而影响了它们的顺序被执行。它们以同步顺序执行是 巧合。如果您切换了事件循环,或引入了更多协程(尤其是一些使用 I/O 的协程),那么顺序很容易再次不同。

此外,您的新协程使用 time.sleep();这会使您的协程 不合作 。事件循环不会通知您的代码正在等待(time.sleep() 不会让步!),因此 无法执行其他协程 time.sleep() 是 运行宁。 time.sleep() 只是 不会 return 或让任何其他代码 运行 直到请求的时间过去。将此与 asyncio.sleep() implementation, which simply yields to the event loop with a call_later() hook 进行对比;事件循环现在知道该任务直到稍后才需要任何关注。

另请参阅 for a more in-depth discussion of how tasks and the event loop interact. And if you must run blocking, synchronous code that can't be made to cooperate, then use an executor pool 以在单独的进程或子进程中执行阻塞代码,从而为其他性能更好的任务释放事件循环。