python3 asyncio

发布时间:2020-04-30 13:23:43编辑:admin阅读(3014)

    一、概述

    asyncio 是用来编写 并发 代码的库,使用 async/await 语法。

    asyncio 被用作多个提供高性能 Python 异步框架的基础,包括网络和网站服务,数据库连接库,分布式任务队列等等。

    asyncio 往往是构建 IO 密集型和高层级 结构化 网络代码的最佳选择。

    asyncio 提供一组 高层级 API 用于:

    此外,还有一些 低层级 API 以支持 库和框架的开发者 实现:

     

    关于asyncio的使用,请阅读以下2篇文章:

    https://blog.csdn.net/SL_World/article/details/86597738

    https://blog.csdn.net/SL_World/article/details/86691747

     

    写的非常不错,强烈推荐!!!

     

    二、功能演示

    subprocess

    需求

    需要ping内网中的所有ip地址,是否都可以pnig通。

    内网网段为:192.168.31.0/24

    完整代码

    test.py

    #!/usr/bin/env python3
    # coding: utf-8
    
    import time
    import subprocess
    import asyncio
    import re
    
    
    async def ping_call(num):
        # 当前时间
        current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        ip = "192.168.31.%s" % num
        # 超时时间为1秒,ping 1次
        cmd = 'ping -c 1 -w 1 -W 1 %s' % ip
        print(cmd)
        # 执行命令
        proc = await asyncio.create_subprocess_exec('ping', '-c', '1','-w','1','-W','1', ip,
                                                stdout=asyncio.subprocess.PIPE)
        # print("proc",proc,type(proc))
        result = await proc.stdout.read()
    
        # 通过正则匹配是否有100%关键字
        regex = re.findall('100% packet loss', result.decode('utf-8'))
        # 长度为0时,表示没有出现100% packet loss
        if len(regex) == 0:
            return current_time,ip,True
        else:
            return current_time,ip,False
    
    
    async def main():  # 调用方
        tasks = []
        for i in range(1, 256):
            # 把所有任务添加到task中
            tasks.append(ping_call(i))
    
        # 子生成器
        done, pending = await asyncio.wait(tasks)
        # done和pending都是一个任务,所以返回结果需要逐个调用result()
        for r in done:
            # print(r.result())
            # 判断布尔值
            if r.result()[2]:
                # 颜色代码
                color_code = 32
            else:
                color_code = 31
    
            info = "\033[1;{};1m{}\033[0m".format(color_code, r.result())
            print(info)
    
    
    if __name__ == '__main__':
        start = time.time()
        # 创建一个事件循环对象loop
        loop = asyncio.get_event_loop()
        try:
            # 完成事件循环,直到最后一个任务结束
            loop.run_until_complete(main())
        finally:
            # 结束事件循环
            loop.close()
        print('所有IO任务总耗时%.5f秒' % float(time.time() - start))

     

    执行输出:

    ...
    ping -c 1 -w 1 -W 1 192.168.31.11
    ...
    ('2020-04-20 18:18:21', '192.168.31.138', False)
    ('2020-04-20 18:18:21', '192.168.31.230', True)
    ('2020-04-20 18:18:21', '192.168.31.1', True)
    ('2020-04-20 18:18:20', '192.168.31.170', False)
    ...
    ('2020-04-20 18:18:20', '192.168.31.200', False)
    所有IO任务总耗时1.93505秒

    可以发现,花费时间为1.9秒。速度特别快!

    如果同步执行,可能需要500多秒。

     

    注意:subprocess模块,是调用asyncio.create_subprocess_exec,它返回一个asyncio生成器对象。

    如果直接调用python自带的subprocess模块,是无法实现异步的。

     

    本文参考链接:

    https://gist.github.com/athoune/0736f73368fac38f066ac7cbf82ff5eb

    http://codingdict.com/sources/py/asyncio/5789.html

     


关键字