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 以在单独的进程或子进程中执行阻塞代码,从而为其他性能更好的任务释放事件循环。
我已经在 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 进行对比;事件循环现在知道该任务直到稍后才需要任何关注。
另请参阅