• 6)协程三( asyncio处理并发)


    一:使用 asyncio处理并发    

     介绍 asyncio 包,这个包使用事件循环驱动的协程实现并发。这是 Python 中最大也是最具雄心壮志的库之一。

    二:示例

      1)单任务协程处理和普通任务比较

    #普通任务示例
        # _*_ coding:utf-8 _*_
        __author__ = "lixiang"
        import asyncio
        import time
        
        def hello():
            count=0
            while count<10:
                print("before",count)
                try:
                    
                    time.sleep(0.1)
                    count+=1
                    print("after",count)
                except Exception as e:
                    print(e)
            return count
        
        if __name__=="__main__":
            start_time=time.time()
            hello()
            end_time=time.time()
            print("cost time",end_time-start_time)
    普通任务示例
    #单任务协程示例
        # _*_ coding:utf-8 _*_
        __author__ = "lixiang"
        import asyncio
        import time
        @asyncio.coroutine# 表示要协程处理
        def hello():
            count=0
            while count<10:
                print("before",count)
                try:
                    #使用 yield from asyncio.sleep(1) 代替 time.sleep(1),
                    yield from asyncio.sleep(0.1)
                    count+=1
                    print("after",count)
                except Exception as e:
                    print(e)
            return count
        
        if __name__=="__main__":
            start_time=time.time()
            loop=asyncio.get_event_loop()
            loop.run_until_complete(hello())
            loop.close()
            end_time=time.time()
            print("cost time",end_time-start_time)
    单任务协程示例

      两种方式处理结果处理时间都是1秒,此时协程并不能体现并发的优势

    # _*_ coding:utf-8 _*_
        __author__ = "lixiang"
        import asyncio
        import time
        @asyncio.coroutine# 要协程处理
        def hello():
            count=0
            while count<10:
                print("before",count)
                try:
                    #使用 yield from asyncio.sleep(0.1) 代替 time.sleep(0.1),这样的休眠不会阻塞事件循环
                    yield from asyncio.sleep(0.1)
                    count+=1
                    print("after",count)
                except Exception as e:
                    print(e)
            return count
        
        @asyncio.coroutine
        def hello_welcome():
            result=yield from hello()
            print(result)
        
        if __name__=="__main__":
            start_time=time.time()
            loop=asyncio.get_event_loop()
            loop.run_until_complete(hello_welcome())
            loop.close()
            end_time=time.time()
            print("cost time",end_time-start_time)
    通过一个协程直接调用另外一协程

      此时也没有显示协程优势

      2)两个任务协程比较

      上面示例,如果hello运行需要1秒,别外一个任务运行也需要1秒。

    # _*_ coding:utf-8 _*_
        __author__ = "lixiang"
        import asyncio
        import time
        @asyncio.coroutine# 要协程处理
        def hello():
            count=0
            while count<10:
                print("before",count)
                try:
                    #使用 yield from asyncio.sleep(0.1) 代替 time.sleep(0.1),这样的休眠不会阻塞事件循环
                    yield from asyncio.sleep(0.1)
                    count+=1
                    print("after",count)
                except Exception as e:
                    print(e)
            return count
        
        @asyncio.coroutine
        def show_hello():
            yield  from asyncio.sleep(1)
            return 666
        
        @asyncio.coroutine
        def hello_welcome():
            """
                安排协程hello的运行时间,这个运行时候根据show_hello来定。
                如果show_hello安排时间为0.5秒,hello时间为0.1秒,10次循环不能正常结束,
                提示Task was destroyed but it is pending!
                如果show_hello安排时间为1秒,hello时间为0.1秒,10次循环能正常结束,
                任务提示:Task finished
            """
            re1=asyncio.async(hello())
            result=yield from show_hello()
            print(re1)
            print("result",result)
        
        if __name__=="__main__":
            start_time=time.time()
            loop=asyncio.get_event_loop()
            loop.run_until_complete(hello_welcome())
            loop.close()
            end_time=time.time()
            print("cost time",end_time-start_time)
    
        #测试结果显示只需要1秒,并发优势显示出来。
        这里我们对hello进行协程运行时间安排。
        安排协程hello的运行时间,这个运行时间根据show_hello来定。
        如果show_hello安排时间为0.5秒,hello时间为0.1秒,10次循环不能正常结束,
        提示Task was destroyed but it is pending!
        如果show_hello安排时间为0.9秒,hello时间为0.1秒,10次循环能正常结束,
        任务提示:Task finished
    两个任务协程比较
    #多任务
        # _*_ coding:utf-8 _*_
        __author__ = "lixiang"
        import asyncio
        import time
        @asyncio.coroutine# 要协程处理
        def hello():
            count=0
            while count<10:
                print("before",count)
                try:
                    #使用 yield from asyncio.sleep(.1) 代替 time.sleep(.1),这样的休眠不会阻塞事件循环
                    yield from asyncio.sleep(0.1)
                    count+=1
                    print("after",count)
                except Exception as e:
                    print(e)
            return count
        
        @asyncio.coroutine
        def show_hello():
            yield  from asyncio.sleep(1)
            return 666
        
        @asyncio.coroutine
        def show_hello2():
            yield  from asyncio.sleep(1)
            return 777
        
        @asyncio.coroutine
        def hello_welcome():
            """
                安排协程hello的运行时间,这个运行时候根据show_hello来定。
                如果show_hello安排时间为0.5秒,hello时间为0.1秒,10次循环不能正常结束,
                提示Task was destroyed but it is pending!
                如果show_hello安排时间为0.9秒,hello时间为0.1秒,10次循环能正常结束,
                任务提示:Task finished
            """
            asyncio.async(show_hello2())
            asyncio.async(hello())
            result=yield from show_hello()
        
            print("result",result)
        
        if __name__=="__main__":
            start_time=time.time()
            loop=asyncio.get_event_loop()
            loop.run_until_complete(hello_welcome())
            loop.close()
            end_time=time.time()
            print("cost time",end_time-start_time)
    多任务
        @asyncio.coroutine# 要协程处理
        def hello():
            count=0
            while count<10:
                print("before",count)
                try:
                    #使用 yield from asyncio.sleep(.1) 代替 time.sleep(.1),这样的休眠不会阻塞事件循环
                    yield from asyncio.sleep(0.1)
                    count+=1
                    print("after",count)
                    yield from asyncio.sleep(0.1)
                except Exception as e:
                    print(e)
    如果 hello里面有两个yield,两者之间是顺序,机每次循环需要0.2

        上面为了执行这些操作,必须排定协程的运行时间,然后使用 asyncio.Task 对象包装协
        程。对协程来说,获取 Task 对象有两种主要方式。    

       asyncio.async(coro_or_future, *, loop=None)

      create_

      上面如果都是通过时间控制协程运行,那如果控制协程的时间怎么设定比较好了,

      时间短了其他协程任务不能运行结束Task was destroyed but it is pending,时间设置长又会耗时长了。
         可以通过asyncio.wait解决
           asyncio.wait(...) 协程的参数是一个由期物或协程构成的可迭代对象; wait 会分别
           把各个协程包装进一个 Task 对象。最终的结果是, wait 处理的所有对象都通过某种方
          式变成 Future 类的实例。 wait 是协程函数,因此返回的是一个协程或生成器对
          象; wait_coro 变量中存储的正是这种对象。为了驱动协程,我们把协程传给
          loop.run_until_complete(...) 方法。虽然函数的名称是 wait,但它不是阻塞型函数。

       wait 是一个协程,等传给它的所有协程运行完毕后结束(这是 wait 函数的默认行为;参见这个示例后面的说明)
        loop.run_until_complete 方法的参数是一个期物或协程。如果是协
        程, run_until_complete 方法与 wait 函数一样,把协程包装进一个 Task 对象中。协
        程、期物和任务都能由 yield from 驱动,这正是 run_until_complete 方法对 wait
        函数返回的 wait_coro 对象所做的事。 wait_coro 运行结束后返回一个元组,第一个元
        素是一系列结束的期物,第二个元素是一系列未结束的期物

        # _*_ coding:utf-8 _*_
        __author__ = "lixiang"
        import asyncio
        import time
        @asyncio.coroutine# 要协程处理
        def hello():
            count=0
            while count<10:
                print("before",count)
                try:
                    #使用 yield from asyncio.sleep(.1) 代替 time.sleep(.1),这样的休眠不会阻塞事件循环
                    yield from asyncio.sleep(0.1)
                    count+=1
                    print("after",count)
                    yield from asyncio.sleep(0.1)
                except Exception as e:
                    print(e)
            return count
        
        @asyncio.coroutine
        def show_hello():
            yield  from asyncio.sleep(1.2)
            return 666
        
        @asyncio.coroutine
        def show_hello2():
            yield  from asyncio.sleep(1.2)
            return 777
        
        # @asyncio.coroutine
        # def hello_welcome():
        #     """
        #         安排协程hello的运行时间,这个运行时候根据show_hello来定。
        #         如果show_hello安排时间为0.5秒,hello时间为0.1秒,10次循环不能正常结束,
        #         提示Task was destroyed but it is pending!
        #         如果show_hello安排时间为0.9秒,hello时间为0.1秒,10次循环能正常结束,
        #         任务提示:Task finished
        #     """
        #     asyncio.async(show_hello2())
        #     asyncio.async(hello())
        #     result=yield from show_hello()
        #
        #     print("result",result)
        
        if __name__=="__main__":
            start_time=time.time()
            loop=asyncio.get_event_loop()
            wait_coro=asyncio.wait([hello(),show_hello(),show_hello2()])
            loop.run_until_complete(wait_coro)
            wait_coro.close()
            loop.close()
            end_time=time.time()
            print("cost time",end_time-start_time)
    asyncio wait使用

        #如果要实时显示那个协程已完成了
        我把一个协程列表传给 asyncio.wait 函数,经由
        loop.run_until_complete 方法驱动,全部协程运行完毕后,这个函数会返回所有下载
        结果。可是,为了更新进度条,各个协程运行结束后就要立即获取结果。在线程池版示例
        中(见示例 17-14),为了集成进度条,我们使用的是 as_completed 生成器函数;幸
        好, asyncio 包提供了这个生成器函数的相应版本

    # _*_ coding:utf-8 _*_
        __author__ = "lixiang"
        import asyncio
        import time
        @asyncio.coroutine# 要协程处理
        def hello():
            count=0
            while count<10:
                print("before",count)
                try:
                    #使用 yield from asyncio.sleep(.1) 代替 time.sleep(.1),这样的休眠不会阻塞事件循环
                    yield from asyncio.sleep(0.1)
                    count+=1
                    print("after",count)
                    yield from asyncio.sleep(0.1)
                except Exception as e:
                    print(e)
            return count
        
        @asyncio.coroutine
        def show_hello():
            yield  from asyncio.sleep(1.2)
            return 666
        
        @asyncio.coroutine
        def show_hello2():
            yield  from asyncio.sleep(1.3)
            return 777
        
        @asyncio.coroutine
        def hello_welcome():
            count=0
            coro=asyncio.as_completed([hello(),show_hello(),show_hello2()])
        
            for future in coro:
                res=yield from future
                print("11111",res)
                count+=1
                print(count)#可以在这里实现进度条功能
            return count
        
        
        if __name__=="__main__":
            start_time=time.time()
            loop=asyncio.get_event_loop()
            counts=loop.run_until_complete(hello_welcome())
            print(counts)
            loop.close()
            end_time=time.time()
            print("cost time",end_time-start_time)
    asyncio as_complated
  • 相关阅读:
    JVM基础(一)—— 运行时内存结构
    SQL if 和 case when查询示例
    SQL分组聚合查询
    My music
    DataX增量同步到ADB ADS时报错
    shell find的用法
    pycharm安装
    在两个库中查找出差异明细
    docker下安装centos
    升级RDS8.0遇到的问题
  • 原文地址:https://www.cnblogs.com/lixiang1013/p/9392895.html
Copyright © 2020-2023  润新知