多任务--协程

多任务--协程

一、协程

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

三、案例--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()
原文地址:https://www.cnblogs.com/Mryang123/p/10003739.html