这篇博客简单的体会一下异步执行的感觉,并且改写一个常见的操作,理解异步的使用场景。
异步的含义是:在程序有一些需要等待的时候,把继续运行的权利交出去,然后等到某个条件达成后再重新申请继续执行,它是相对于“同步”而出现的词。
同步与异步的区别:
类比成生活就是:一个小人,有两个作业:1. 线上平板刷课10分钟;2. 做口算题5分钟
- 同步:小人,先刷课,用了10分钟,然后做口算题,用了5分钟,一共耗时15分钟
- 异步:小人,平板挂着课程,去做口算题,用了5分钟,这时线上课程也过了5分钟,所以只需要再等5分钟即可完成作业,一共耗时10分钟
异步与并行的区别:
- 并行:变出三头六臂同时进行所有任务
- 异步:任务还是一个一个完成,但疯狂压榨自己可能空闲的一切时间,在多个任务之间来回切换,赶进度
常规顺序执行的函数
对于一个如下的一般的程序:
import time
def my_task(number):
print("begin task {} 时间:{}".format(number, time.time()))
time.sleep(1)
print('====== task {} 时间:{} ======='.format(number, time.time()))
if __name__ == '__main__':
for i in range(5):
my_task(i)
得到的结果是:
begin task 0 时间:1658886603.399502
====== task 0 时间:1658886604.399808 =======
begin task 1 时间:1658886604.39987
====== task 1 时间:1658886605.4036212 =======
begin task 2 时间:1658886605.4036832
====== task 2 时间:1658886606.408043 =======
begin task 3 时间:1658886606.4081228
====== task 3 时间:1658886607.408743 =======
begin task 4 时间:1658886607.4087849
====== task 4 时间:1658886608.413343 =======
程序按照既定的程序,按部就班的循序执行并得到想要的结果
用异步操作改写函数
改写的步骤如下:
- 导入异步操作的包(python3.5+):
import asyncio
- 在可能需要交出控制权的函数前面添加
async
关键词 - 在函数内部可以交出控制权的函数前添加
await
关键词 - 最后通过一个普通函数的
asyncio.get_event_loop()
执行异步操作
import time
import asyncio
async def my_async_task(number):
print("begin task {} 时间:{}".format(number, time.time()))
# await 是主动告诉程序在这里可以把程序的使用权交出去
# 使用 asyncio.sleep(1) 是指模拟1秒的等待操作
await asyncio.sleep(1)
print('====== task {} 时间:{} ======='.format(number, time.time()))
if __name__ == '__main__':
loop = asyncio.get_event_loop()
tasks = []
for i in range(5):
tasks.append(my_async_task(i))
loop.run_until_complete(asyncio.wait(tasks))
得到的结果如下:
begin task 3 时间:1658906069.224732
begin task 0 时间:1658906069.224763
begin task 4 时间:1658906069.224777
begin task 1 时间:1658906069.224789
begin task 2 时间:1658906069.224799
====== task 3 时间:1658906070.2289789 =======
====== task 0 时间:1658906070.2290099 =======
====== task 4 时间:1658906070.229023 =======
====== task 1 时间:1658906070.229034 =======
====== task 2 时间:1658906070.229046 =======
可以看到:
- 程序在执行到
await
时,都主动交出了程序的控制权,并继续执行循环操作 - 在循环的函数里是线性的执行,但是执行顺序是随机的
因此,异步操作可以使用:
-
任意的函数都可以使用异步操作,因为在函数内部是线性操作
-
异步的函数就像是一个圈子,圈子里的任务需要加上
async
关键词,这些任务不能摸鱼,异步之外的函数没有要求。异步操作的内、外通过如下代码衔接:loop = asyncio.get_event_loop() tasks = [] for i in range(5): tasks.append(my_async_task(i)) loop.run_until_complete(asyncio.wait(tasks))
以上便是异步操作的基本模版,后续的内容会继续深入,并用异步操作改写任意的代码
异步操作是比较高阶的用法,也是能够有效发挥程序效率的一个方法。执行异步的函数前后逻辑对大家的逻辑要求比较高,不是很容易梳理逻辑的,需要慢慢理解和练习