目标
之前翻译的 Andrew Crozier 使用 asyncio 的一个指南 里有对 python 异步相关的关键词,以及 asyncio 的接口的基础介绍与范例。
本篇目标是实践 asyncio 的最基础的操作。
无异步的一般情况
为了说明“异步”的特点,先看下无异步的情况,即一般的情况:
DoSomething
是个测试函数,假设了某人用了几秒做某事,而且做事的时候每隔1秒都会打印信息:
import time
#假设某人用了几秒做某事:
def DoSomething(someone, seconds):
for i in range(seconds):
time.sleep(1) #等待1秒模拟在做某事
print(someone + " doing things:" + str(i)) #间隔1秒打印信息
if __name__=='__main__':
DoSomething("jack",3)
DoSomething("ming",4)
那么,当直接调用两次这个函数,分别让 jack 做3秒,ming 做4秒时。理所当然会有下面的输出:
jack doing things:0
jack doing things:1
jack doing things:2
ming doing things:0
ming doing things:1
ming doing things:2
ming doing things:3
而如果想要 jack 和 ming 同时做事,那就需要异步的操作了:
异步的情况(并行)
首先需要在函数名前加async
来表明它是个异步函数。接着就要用到 asyncio 库中的一些接口了:
import asyncio
#假设某人用了几秒做某事:
async def DoSomething(someone, seconds):
for i in range(seconds):
await asyncio.sleep(1) #等待1秒模拟在做某事
print(someone + " doing things:" + str(i)) #间隔1秒打印信息
if __name__=='__main__':
#获得 event loop:
loop = asyncio.get_event_loop()
#待执行的异步函数:
tasks = [
asyncio.ensure_future(DoSomething("jack",3)),
asyncio.ensure_future(DoSomething("ming",4)),
]
#开始执行:
loop.run_until_complete(asyncio.gather(*tasks))
简单来说:
- 先通过
asyncio.get_event_loop()
获得 event loop - 然后通过
asyncio.ensure_future
获得任务对象 - 再用
asyncio.gather
收集要执行的任务对象的列表 - 最后调用 event loop 的
run_until_complete
来执行这些任务。
代码执行后,将会看到:
jack doing things:0
ming doing things:0
jack doing things:1
ming doing things:1
jack doing things:2
ming doing things:2
ming doing things:3
可以看出他们确实是并行执行了。
另一种写法
Andrew Crozier 使用 asyncio 的一个指南 中出现的范例是另一种写法,效果是一样的,但需要更新的python版本。
使用那个写法改写后代码如下:
import asyncio
#假设某人用了几秒做某事:
async def DoSomething(someone, seconds):
for i in range(seconds):
await asyncio.sleep(1) #等待1秒模拟在做某事
print(someone + "doing things:" + str(i)) #间隔1秒打印信息
async def DoAllWork():
#待执行的异步函数:
await asyncio.gather(
DoSomething("jack",3),
DoSomething("ming",4),
)
if __name__=='__main__':
#开始执行:
asyncio.run(DoAllWork())