• 多任务异步协程,asyncio及aiohttp


    要实现异步协程,需要满足几个条件:

      1,创建协程对象,且协程内部操作需要支持异步。

      2,创建任务对象,如需为协程执行结果进行进一步处理,则需要为任务对象绑定回调函数。

      3,创建事件循环,并将任务启动。

      1 import asyncio
      2 import requests
      3 from lxml import etree
      4 import aiohttp
      5 import os
      6 
      7 headers = {
      8 
      9     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
     10 }
     11 
     12 
     13 # 普通单线程,同步执行任务
     14 # url_ = 'https://www.qiushibaike.com/pic/page/{}/'
     15 # for i in range(1, 100):
     16 #     url = url_.format(i)
     17 #
     18 #     ret = requests.get(url=url, headers=headers).text
     19 #     tree = etree.HTML(ret)
     20 #     url_list = tree.xpath('//div[@id="content-left"]/div/div/a/img/@src')
     21 #     for url in url_list:
     22 #         name = url.split('/')[-1]
     23 #         print(name)
     24 #         img_url = 'https:' + url
     25 #         img = requests.get(img_url, headers=headers).content
     26 #         with open(os.path.join('qiutu',name), 'wb') as f:
     27 #             f.write(img)
     28 
     29 # 使用async修饰过的函数,调用函数时,函数不执行,而是生成了一个协程对象
     30 async def get_img(url):
     31     """
     32     # aiohttp的细节处理:
     33     # asnyc:硬性的语法要求关键字,应用aiohttp的代码模块
     34     # await: 会出现阻塞的操作的代码中,需要用await修饰
     35 
     36     """
     37 
     38     # ret = requests.get(url=url, headers=headers).text
     39     name = url.split('/')[-1]
     40 
     41     # 固定写法,aiohttp.ClientSession(),实例化一个异步请求对象
     42     async with  aiohttp.ClientSession() as aio:
     43         # 用该对象向url发送异步请求
     44         async with await aio.get(url=url, headers=headers) as ret:
     45             # 将响应对象(图片)读取为二进制流,以便存储。(.text().json().read())对应requests的(.text.json.content)
     46             res = await ret.read()
     47 
     48     return name, res
     49 
     50 
     51 # 定义一个回调函数(名字随意),回调函数接收该任务对象本身,(像self)
     52 def callback(task):
     53     # task.result()接收协程(特殊函数执行的返回结果,可进一步处理)
     54     name, res = task.result()
     55     # 将二进制流持久化成本地文件
     56     with open(os.path.join('qiutu', name), 'wb') as f:
     57         f.write(res)
     58     print(name, '下载完成')
     59 
     60 
     61 # 通过糗图百科通用页面url,生成十页数据,并将十页数据中的所有图片链接存到urls中
     62 urls = []
     63 url_ = 'https://www.qiushibaike.com/pic/page/{}/'
     64 for i in range(1, 10):
     65     page_url = url_.format(i)
     66     ret = requests.get(url=page_url, headers=headers).text
     67     # 通过xpath定位并获取糗图图片的src
     68     tree = etree.HTML(ret)
     69     url_list = tree.xpath('//div[@id="content-left"]/div/div/a/img/@src')
     70     # 将每个图片的url存到urls中
     71     for img_url in url_list:
     72         urls.append(img_url)
     73         print(img_url)
     74 
     75 tasks = []
     76 
     77 for url in urls:
     78     url = 'https:' + url
     79     # 执行协程对象函数(函数并不会真正去执行,而是生成一个协程对象)
     80     cor = get_img(url)
     81     # 将协程对象添加。生成一个任务对象
     82     # task = asyncio.create_task(cor)       # python3.7新加入
     83     task = asyncio.ensure_future(cor)
     84     # 为任务对象绑定添加一个回调函数,传入函数名
     85     task.add_done_callback(callback)
     86     # 将所有的任务对象添加到任务列表中
     87     tasks.append(task)
     88 
     89 # 获取当前事件循环对象(没有则创建),asyncio.new_event_loop()是创建事件循环
     90 loop = asyncio.get_event_loop()
     91 
     92 # run_until_complete:运行直到 future (可等待任务对象) 被完成。
     93 
     94 # 将任务列表加入事件循环,并发开始执行
     95 # 请注意此函数不会引发 asyncio.TimeoutError。当超时发生时,未完成的 Future 或 Task 将在指定秒数后被返回,指定timeout参数。
     96 loop.run_until_complete(asyncio.wait(tasks))
     97 
     98 # asyncio.gather:如果所有可等待对象都成功完成,结果将是一个由所有返回值聚合而成的列表。结果值的顺序与 aws 中可等待对象的顺序一致。
     99 # 如果发生超时,任务将取消并引发 asyncio.TimeoutError.
    100 # loop.run_until_complete(asyncio.gather(tasks))

    注意!:

      一个线程内最多大概可以注册500个协程。。任务数过多,需要多线程加异步协程实现。

  • 相关阅读:
    20182318 2019-2020-1 《数据结构与面向对象程序设计》第2和3周学习总结
    20182318 2019-2020-1 《数据结构与面向对象程序设计》实验二报告
    实验一
    第一周作业
    20182318预备作业:课程基础
    WEB前端第五十八课——PDO预处理、PDO事务处理
    WEB前端第五十七课——单例模式、PDO、singleton获取PDO、PDO操作DB、PDO异常捕获
    WEB前端第五十六课——MySQL、前后台交互
    WEB前端第五十五课——jQueryAjax请求
    WEB前端第五十四课——PHP基础⑵流程控制、类和对象、常量和变量、构造函数、继承
  • 原文地址:https://www.cnblogs.com/NoteBook3013/p/11109992.html
Copyright © 2020-2023  润新知