zoukankan      html  css  js  c++  java
  • 对python async与await的理解

            async/await关键字是出现在python3.4以后。网上已经有很多文章对async/await这两个关键字都有讲解,包括如何由python2的yield from发展到async/await这两个关键字,以及一些代码实现都有。但是对于像我这样初次接触的人来说,光看代码分析也不一定能理解,我也是在度娘上搜索很多相关的网站,当中也有官网,都没有发现能让我一眼看懂在什么地方可以用await,什么情况用await的文章。经过自己的重新思考,总算对async、await有一些初步的了解,所以想把自己的理解记录下来,希望对一些学习协程或者异步的初学者也有一定的帮助。

    对于网上能搜到的一些代码实现、例子,这里就不重复了。

    一、首先要知道什么是协程、异步。

    举个例子:假设有1个洗衣房,里面有10台洗衣机,有一个洗衣工在负责这10台洗衣机。那么洗衣房就相当于1个进程,洗衣工就相当1个线程。如果有10个洗衣工,就相当于10个线程,1个进程是可以开多线程的。这就是多线程!

    那么协程呢?先不急。大家都知道,洗衣机洗衣服是需要等待时间的,如果10个洗衣工,1人负责1台洗衣机,这样效率肯定会提高,但是不觉得浪费资源吗?明明1 个人能做的事,却要10个人来做。只是把衣服放进去,打开开关,就没事做了,等衣服洗好再拿出来就可以了。就算很多人来洗衣服,1个人也足以应付了,开好第一台洗衣机,在等待的时候去开第二台洗衣机,再开第三台,……直到有衣服洗好了,就回来把衣服取出来,接着再取另一台的(哪台洗好先就取哪台,所以协程是无序的)。这就是计算机的协程!洗衣机就是执行的方法。

    当你程序中方法需要等待时间的话,就可以用协程,效率高,消耗资源少。

    好了!现在来总结一下:

    洗衣房 ==> 进程

    洗衣工 ==> 线程

    洗衣机 ==> 方法(函数)

    二、asyncawait 的使用

    正常的函数在执行时是不会中断的,所以你要写一个能够中断的函数,就需要添加async关键。

    async 用来声明一个函数为异步函数,异步函数的特点是能在函数执行过程中挂起,去执行其他异步函数,等到挂起条件(假设挂起条件是sleep(5))消失后,也就是5秒到了再回来执行。

    await 用来用来声明程序挂起,比如异步程序执行到某一步时需要等待的时间很长,就将此挂起,去执行其他的异步程序。await 后面只能跟异步程序或有__await__属性的对象,因为异步程序与一般程序不同。假设有两个异步函数async a,async b,a中的某一步有await,当程序碰到关键字await b()后,异步程序挂起后去执行另一个异步b程序,就是从函数内部跳出去执行其他函数,当挂起条件消失后,不管b是否执行完,要马上从b程序中跳出来,回到原程序执行原来的操作。如果await后面跟的b函数不是异步函数,那么操作就只能等b执行完再返回,无法在b执行的过程中返回。如果要在b执行完才返回,也就不需要用await关键字了,直接调用b函数就行。所以这就需要await后面跟的是异步函数了。在一个异步函数中,可以不止一次挂起,也就是可以用多个await。

    三、实例:

     1 async def test2(i):
     2     r = await other_test(i)
     3     print(i,r)
     4 
     5 async def other_test(i):
     6     r = requests.get(i)
     7     print(i)
     8     await asyncio.sleep(4)
     9     print(time.time()-start)
    10     return r
    11 
    12 url = ["https://segmentfault.com/p/1210000013564725",
    13        "https://www.jianshu.com/p/83badc8028bd",
    14        "https://www.baidu.com/"]
    15 
    16 loop = asyncio.get_event_loop()
    17 task = [asyncio.ensure_future(test2(i)) for i in url]
    18 start = time.time()
    19 20 loop.run_until_complete(asyncio.wait(task))
    21 endtime = time.time()-start
    22 print(endtime)
    23 loop.close()

    输出结果:

     1 https://segmentfault.com/p/1210000013564725
     2 https://www.jianshu.com/p/83badc8028bd
     3 https://www.baidu.com/
     4 4.425147771835327
     5 https://segmentfault.com/p/1210000013564725 <Response [200]>
     6 4.5975635051727295
     7 https://www.jianshu.com/p/83badc8028bd <Response [403]>
     8 4.722797632217407
     9 https://www.baidu.com/ <Response [200]>
    10 4.722797632217407

    对于下面这几行代码:

    loop = asyncio.get_event_loop()
    task = [asyncio.ensure_future(test2(i)) for i in url]
    loop.run_until_complete(asyncio.wait(task))
    loop.close()
    可以在网上找到具体讲解,在这可用下图来粗略形容一下

    当所有的异步程序运行完就会返回最后结果。
    对于什么是task和future,asyncio.wait()与asyncio.gather()、asyncio.ensure_future()这些大家可以网上找到解释。

    说到这里,相信你也大概清楚在什么时候用async、什么时候await了吧! 如果有说得不对的地方,请多多指正!!

  • 相关阅读:
    centos 6.5 查看、开启,关闭 端口
    centos 安装 nginx
    centos 安装 svn
    centos 安装 maven
    (转)不停止Nginx服务的情况下平滑变更Nginx配置
    记录1---python+linux+vim之while循环语句使用
    记录1---linux系统之创建用户,用户登录,查看用户名,切换用户登录,退出登录
    记录——Fiddler5.0 中文版 绿色免费版 汉化破解版安装
    fiddler笔记1---fiddler的安装 和 证书安装 以及 证书导出失败问题解决
    fiddler笔记2--fiddler工具界面的功能使用与介绍
  • 原文地址:https://www.cnblogs.com/xinghun85/p/9937741.html
Copyright © 2011-2022 走看看