今天我们学异步协程

  • 概念
  • 第一个案例
  • 第二个案例
  • 实现异步下载图片
    • 整体的思路流程
  • 很黄很暴力

概念

  1. event_loop:事件循环,也就是通过不断的循环获取任务的状态(完成/未完成)来分配任务。
  2. coroutine:协程对象,python中万物皆对象,不多说,懂的都懂。
  3. task:任务对象,对协程对象进行包装,加上了状态,完成和未完成。
  4. future:和task一样,只不过可以提前包装。
  5. async:定义一个协程,定义!
  6. await:挂起阻塞的操作,还记得之前说的IO等待吗,在那前面就要用到这个。

第一个案例

第一步,导入我们的asyncio模块,async+io!!!

第二步,用async定义一个协程,定义!

记住用await挂起阻塞的操作,也就是asyncio.sleep(2),这里是为了模拟下载所需要花费的时间!

awa

第三步,创建一个协程对象,对象,懂的都懂!

第四步,用event_loop创建一个事件循环,也就是游戏里的任务公布栏之类的~

第五步,是不是觉得该把任务对象方法事件循环中了??还真是的!

然后执行,就会成功执行我们的async函数:

第二个案例

那么这个时候就要有人问了,刚开始说的1,2,5,6都用上了,那3,4呢,3,4呢,3,4呢……
这就给大家用上!
task

  • 这里我们就把duixiang这个协程对象放置到task任务对象,然后再把task任务对象放到任务列表中:

    那么到这里就有人问了,用task和不用task又没有区别,为什么要用task呢?

我们来打印一下任务完成前后的task!

看到没有!!task给每个任务都贴上了标签,让循环器更好的去筛选哪些是完成了的,哪些是没完成的!

future也是一样的,这里就不多说了,我们主要用task。

实现异步下载图片

昨天呢,我们本来是要用异步实现下载图片的,但是遇到了一个小问题,那就是requests模块它不支持异步,那我们也没有办法强人锁男的啦,人各有志,让我们工地见面。

好啦,教大家一个支持异步的同时也支持requests功能的新模块!

aiohttp aiohttp aiohttp aiohttp aiohttp ……

aiohttp

首先,环境安装!

pip install aiohttp

当然你也可以在pycharm里直接搜索安装模块!

安装完了这个模块之后呢,先不要急,先想一个问题:

我们既然有了进程池,又有了异步,是不是可以把他们结合起来呢?是的!!

所以就有一个东西,叫做多线程异步协程。也就是说每个线程里的程序都能进行异步!!! 如果还是听不懂的话…那就照着用,毕竟用起来也是不难的,因为异步协程这一部分知识呢,是属于基础进阶那一块的,想要详细说又要花很多篇幅,如果你实在是想学,或者实在是对基础不太熟练,那就留个言,如果反映人数够多的话,小泽就专门开一个基础的坑,带大家一起学python的基础!

但是先告诉大家有这个东西,今天呢,我们还是只来实现多任务异步协程,而不是多线程异步协程!

整体的思路流程

我们已经有了aiohttp,心里就会很踏实也很安心,所以先按照流程来,这次跟着小泽的思路走:

第一步,我们先写一个下载图片的函数:

# 定义一个函数,需要传入url参数
def func(url):
	# UA伪装
    headers = { 
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
    }
    # 向图片的网址发起请求,获取二进制数据
    response = requests.get(url=url,headers=headers).content
    # 用上下文管理器保存
    name = url.split('/')[-1]
    with open(name,'wb') as fp:
        fp.write(response)

路人:你明明说了requests不能用,你还用,你是不是傻!

害,这里不就是用一下嘛,方便我们思路的继续进行,听懂掌声~

第二步,找到我们的三张图片,如果你比较懒,你肯定很懒,那就用小泽给大家准备的三张图片好了:

urls = ['https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_01.png',
        'https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_02.png',
        'https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_03.png'
        ]

放心,不是什么美女 美丽的图片,只是一些正常的图片~

第三步,建立一个循环,把urls里的url依次放入函数中……

等等!这样不就成了同步的操作,说好的多任务异步协程呢!

所以真正的第三步是用循环把所有任务都封装起来:

# 建立任务列表
tasks = []
# 遍历出每一个url
for url in urls:
    # 协程对象
    a = func(url)
    # 封装
    task = asyncio.ensure_future(a)
    # 把封装好的任务加到任务列表里
    tasks.append(task)

当然,也不要忘了给我们的函数,加上async,这样才能让系统知道这个函数是个协程函数!

然后接下来,就是建立事件循环,再把我们的任务列表放进事件循环中!

# 建立事件循环
loop = asyncio.get_event_loop()
# 把任务列表放到事件循环中
loop.run_until_complete(asyncio.wait(tasks))

因为是任务列表,而不是单个任务,所以前面要加上asyncio.wait() 不加的统统拉出去,这么嚣张还想开军舰!

好的,整段写完,剩下的唯一一个问题就是requests模块的问题啦,现在我们就开始说,到底要怎么用aiohttp~

直接上代码!

async def func(url):
    headers = { 
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
    }
    # 方便我们直观看到异步的效果
    print('开始下载',url)
    # 类似于上下文管理器,就是with open,with前面一定要加async,固定写法
    # as session是类似起名字一样
    async with aiohttp.ClientSession() as session:
        # async with跟上面同理,await是手动挂起,因为向图片发起请求是IO操作
        async with await session.get(url=url,headers=headers) as response:
            # 同样的,对返回的数据进行解析也是IO操作
            # 不同于requests模块,read()指的是解析二进制数据
            # text() 就是我们平时用的text
            # 而json对象则要用json()
            data = await response.read()
            # 对url最后的部分进行截取
            name = url.split('/')[-1]
            with open(name,'wb') as fp:
                fp.write(data)
    print('下载完成',url)

我们只需要把func这个协程对象,改成如上所述的内容就可以啦!

至于为什么呢,用法就是上面那样用的,如果看代码看不懂的话…可能是前面几章你没有好好看,当然如果真的真的看不懂,不要怕,先能看懂多少看懂多少,更详细的我们之后再说,在评论区留下你的疑惑和想跟小泽说的话,么么哒~

然后直接运行,揍你!

看着下载效率,多棒啊,我好了,你们呢~

关于多任务异步协程呢,就先到这里了,更详细的要放到不知道哪一篇讲了,因为很多小伙伴在催着要讲模拟登陆这一块了……

很黄很暴力

没广告,没卖课,只有一群爱学习的小伙伴,如果你基础薄弱,或者想搞些大的,欢迎加进来!!!

小泽爱你们,(づ ̄ 3 ̄)づ

本文地址:https://blog.csdn.net/BcXbHello/article/details/110873328