zoukankan      html  css  js  c++  java
  • 8、Python Asyncio异步编程-事件循环详解【2】

    • 异步协程

      • wait()方法的作用
      • wait方法的参数只能是任务列表,作用:wait可以将任务列表中的每一个任务对象进行可挂起操作
      • 挂起 可以让当前被挂起的任务对象交出CPU的使用权
    • 实现异步的原理:

      • 当任务列表被wait方法修饰且已经被注册到事件循环中后,loop就会先去执行第一个任务对象,
        在执行任务对象的过程中,如果遇到了阻塞操作,则当前任务对象会被挂起,然后loop会被执行下一个任务对象,
        每当在执行任务对象时,只有遇到阻塞操作当前任务对象都会被挂起,loop去执行下一个任务对象
        当一个挂起的任务对象的阻塞操作结束后,loop会回头执行其阻塞操作后面的操作
    • 重要点:

      • 在特殊函数内部不可以出现不支持异步的模块代码,否则会中断整个异步效果
    • 关键字await,修饰特殊函数内部阻塞的操作,

      • loop一定会执行阻塞操作,只不过在阻塞时间内可以执行其他后续操作
    • 支持异步网络请求的模块:aiohttp

      • pip install aiohttp
        使用:

        • 1.大致架构

            async with aiohttp.ClientSession() as s:
                # get post方法的使用和requests几乎一致
                # 处理代理:proxy=‘http://ip:port’
                async with s.get(url) as response:
                    # text()字符串形式的响应数据
                    # read()bytes类型的响应数据
                    page_text = response.text()
            return page_text
          
        • 补充细节:

          • 在每一个with前加async关键字

          • 需要在阻塞操作前加上await关键字

          • 完整代码

            async def get_request(url):
                print('正在请求:',url)
                async with aiohttp.ClientSession() as s:
                    # get post方法的使用和requests几乎一致
                    # 处理代理:proxy=‘http://ip:port’
                    async with await s.get(url) as response:
                        # text()字符串形式的响应数据
                        # read()bytes类型的响应数据
                        page_text = await response.text()
                return page_text
            
    • 多任务异步协程的特点:

      • 1.通过requests+xpath可以先将爬取数据的URL进行提取
      • 2.需要将请求的url全部封装到列表中
      • 3.基于列表生成多个任务对象

    完整代码异步请求

    import asyncio
    import requests
    import time
    import aiohttp
    
    start = time.time()
    urls = [
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
    ]
    
    # async def get_request(url):
    #
    #     print('正在请求:',url)
    #     # requests是不支持异步,不可以出现在特殊函数内部
    #     page_text = requests.get(url)
    #     return page_text
    
    async def get_request(url):
        print('正在请求:',url)
        async with aiohttp.ClientSession() as s:
            # get post方法的使用和requests几乎一致
            # 处理代理:proxy=‘http://ip:port’
            async with await s.get(url) as response:
                # text()字符串形式的响应数据
                # read()bytes类型的响应数据
                page_text = await response.text()
        return page_text
    
    
    tasks = []
    for url in urls:
        c = get_request(url)
        task =  asyncio.ensure_future(c)
        tasks.append(task)
    
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)
    
    >>>
    正在请求: http://127.0.0.1:5000/bobo
    正在请求: http://127.0.0.1:5000/jay
    正在请求: http://127.0.0.1:5000/tom
    总耗时: 2.007049560546875
    

    完整代码进行异步解析

    import asyncio
    import aiohttp
    import time
    from lxml import etree
    
    
    start = time.time()
    urls = [
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
    ]
    
    def parse(task):
        page_text = task.result()
        tree = etree.HTML(page_text)
        data = tree.xpath('//a[@id="feng"]/text()')
        print(data)
    
    
    async def get_request(url):
        async with  aiohttp.ClientSession() as s:
            async with await s.get(url) as response:
                page_text = await response.text()
        return page_text
    
    tasks = []
    for url in urls:
        c = get_request(url)
        task = asyncio.ensure_future(c)
        task.add_done_callback(parse)
        tasks.append(task)
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)
    
    >>>
    ['凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘']
    ['凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘']
    ['凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘']
    总耗时: 2.007239580154419
    
    
  • 相关阅读:
    已知: 每个飞机只有一个油箱, 飞机之间可以相互加油(注意是相互,没有加油机) 一箱油可供一架飞机绕地球飞半圈,问题:为使至少一架飞机绕地球一圈回到起飞时的飞机
    简易vector的实现
    简单的内存池实现
    归并排序,递归与非递归
    堆排序
    位运算
    二叉树的建立,以及非递归遍历
    “云端融合”思想的自我摸索(很不靠谱)
    linux android开发环境搭建
    Android系统架构及内核简介
  • 原文地址:https://www.cnblogs.com/remixnameless/p/13171203.html
Copyright © 2011-2022 走看看