这篇博客简单的体会一下异步执行的感觉,并且改写一个常见的操作,理解异步的使用场景。


文章目录

  • 常规顺序执行的函数
  • 用异步操作改写函数


异步的含义是:在程序有一些需要等待的时候,把继续运行的权利交出去,然后等到某个条件达成后再重新申请继续执行,它是相对于“同步”而出现的词。

同步与异步的区别:

类比成生活就是:一个小人,有两个作业: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 =======

程序按照既定的程序,按部就班的循序执行并得到想要的结果

用异步操作改写函数

改写的步骤如下:

  1. 导入异步操作的包(python3.5+):import asyncio
  2. 在可能需要交出控制权的函数前面添加async关键词
  3. 在函数内部可以交出控制权的函数前添加await关键词
  4. 最后通过一个普通函数的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 =======

可以看到:

  1. 程序在执行到await时,都主动交出了程序的控制权,并继续执行循环操作
  2. 在循环的函数里是线性的执行,但是执行顺序是随机的

因此,异步操作可以使用:

  1. 任意的函数都可以使用异步操作,因为在函数内部是线性操作
  2. 异步的函数就像是一个圈子,圈子里的任务需要加上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))

以上便是异步操作的基本模版,后续的内容会继续深入,并用异步操作改写任意的代码

异步操作是比较高阶的用法,也是能够有效发挥程序效率的一个方法。执行异步的函数前后逻辑对大家的逻辑要求比较高,不是很容易梳理逻辑的,需要慢慢理解和练习