• 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
    
    
  • 相关阅读:
    Codeforces Round #632 (Div. 2) D-Challenges in school №41(模拟好题)
    余数求和
    B. 齐心抗疫
    MyBatis源码分析
    关于Idea中右边的maven projects窗口找不到了如何调出来
    IDEA java类文件左下角出现红色的J标识,解决方法
    Postman Tests脚本的使用
    JSONPath解析json
    Postman + Newman 生成测试报告
    TestNG 多线程测试
  • 原文地址:https://www.cnblogs.com/remixnameless/p/13171203.html
Copyright © 2020-2023  润新知