zoukankan      html  css  js  c++  java
  • 多任务--协程

    多任务--协程

    一、协程

    二、进程、线程、协程的区别和应用场景

    三、案例--gevent多任务下载图片

    回到顶部

    一、协程

      1.概念:协程,又称微线程,纤程,也称为用户级线程,在不开辟线程的基础上完成多任务,也就是在单线程的情况下完成多任务,多个任务按照一定顺序交替执行 通俗理解只                        要在def里面只看到一个yield关键字表示就是协程

      2.gevent:

        模块gevent 中 的monkey 可以破解 time.sleep recv accept 等

        使用gevent编写多协程,不使用monkey进行任务切换, 不是多任务的

        使用gevent  创建协程 自动运行

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:Mr.yang
    from gevent import monkey
    monkey.patch_all() # 破解代码 实现任务切换 默认不能自动切换
    import gevent
    import time
                        # 能够切换的操作: time.sleep() recv accept
    # 不加monkey 不是多任务 的协程
    
    def worker(no):
        for i in range(5):
            print("这是协程 %s %s" % (no, gevent.getcurrent()))
            time.sleep(1) # gevent.sleep(1)
    
    def main():
        # 创建协程 自动运行
        g1 = gevent.spawn(worker, 1111)
        g2 = gevent.spawn(worker, 2222)
    
        # 阻塞等待协程执行完成 - 主要是让主进程主线程阻塞在这里
        # g1.join()
        # g2.join()
        gevent.joinall([g1, g2])
    
    if __name__ == '__main__':
        main()
    
    """ 代码结果 """
    这是协程 1111 <Greenlet at 0x211b025c178: worker(1111)>
    这是协程 2222 <Greenlet at 0x211b025c340: worker(2222)>
    这是协程 1111 <Greenlet at 0x211b025c178: worker(1111)>
    这是协程 2222 <Greenlet at 0x211b025c340: worker(2222)>
    gevent创建多协程
    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:Mr.yang
    import time
    
    def work1():
        while True:
            print("-----work1------")
            yield
            time.sleep(0.5)
    
    def work2():
        while True:
            print("-----work2------")
            yield
            time.sleep(0.5)
    
    if __name__ == '__main__':
        # 创建生成器对象
        w1 = work1()
        w2 = work2()
        while True:
            next(w1)
            next(w2)
    
    """ 执行结果 """
    -----work1------
    -----work2------
    -----work1------
    -----work2------
    使用yelid创建简单的多协程
    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:Mr.yang
    import time
    import greenlet
    
    def work1():
        while True:
            print("-----work1------")
            time.sleep(0.5)
            g2.switch()
    
    def work2():
        while True:
            print("-----work2------")
            time.sleep(0.5)
            g1.switch()
    
    if __name__ == '__main__':
        # 创建生成器对象
        g1 = greenlet.greenlet(work1)
        g2 = greenlet.greenlet(work2)
        g1.switch()
    
    """ 执行结果 """
    -----work1------
    -----work2------
    -----work1------
    -----work2------
    greenlet创建多协程

    二、进程、线程、协程的区别和应用场景

      1.区别

    1. 进程是资源分配的单位
    2. 线程是操作系统调度的单位
    3. 进程切换需要的资源最大,效率很低
    4. 线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
    5. 协程切换任务资源很小,效率高
    6. 多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发

      2.应用场景

    1.  资源消耗不关心 要求稳定 用户多进程
    2. ​ 资源消耗关心 多线程或者协程
    3. ​ 多任务的网络程序 建议优先使用协程

    三、案例--gevent多任务下载图片

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:Mr.yang
    from gevent import monkey
    # monkey.patch_all()
    import urllib.request
    import gevent
    import time
    
    def down_img(url):
        """下载指定路径的图片 参数就是图片的链接-网址 URL URI"""
        #
        # "https://2018/10/15/922c4f46586103d3e4ac76d1930a95b1.png",
        file_name = url[url.rfind("/") + 1:]
        print("开始下载图片 %s" % file_name)
    
        # 2.响应对象<网页数据> 请求 打开网址
        response = urllib.request.urlopen(url)
    
        # 3.解析其中数据 bytes
        data = response.read()
    
        # 4.写入文件
        with open(file_name, "wb") as file:
            file.write(data)
        print("完成下载图片 %s" % file_name)
    
    def main():
        begin = time.time()
        # 1.创建协程
        img_list = [
            "https://rpic.douyucdn.cn/live-cover/roomCover/2018/10/15/922c4f46586103d3e4ac76d1930a95b1.png",
            "https://rpic.douyucdn.cn/live-cover/roomCover/2018/07/24/f26f76b07852b37430792745a66be94b.jpg"
        ]
        g1 = gevent.spawn(down_img, img_list[0])
        g2 = gevent.spawn(down_img, img_list[1])
        # 2.等待协程执行完成
        gevent.joinall([g1, g2])
        end = time.time()
        print("花费%f秒" % (end - begin))
    
    if __name__ == '__main__':
        main()
  • 相关阅读:
    JSP,TOMCAT,JD,mysql环境搭建和连接数据库
    jsp基础学习记录
    将d盘根目录下的troydll.dll插入到ID为4000的进程中
    WebSocket内部原理
    基于流(Comet Streaming)
    短轮询
    DjangoWebSocket
    01WebSocket是什么
    Python实现WebSocket
    WebSocket
  • 原文地址:https://www.cnblogs.com/Mryang123/p/10003739.html
Copyright © 2011-2022 走看看