协程-greenlet,gevent

1 篇文章 0 订阅
1 篇文章 0 订阅

前面说过yield实现多任务,但是yield实现多任务,是通过主函数控制的,如果程序里有很多个函数,那么使用next()方法,就得一个一个的执行,所有的函数必须等待,灵活性不够。这里使用greenlet,就可以实现函数的灵活性,greenlet拿的是yield封装。

t1,t2都是全局变量;greenlet 需要通过sudo pip install greenlet(如果你的ubuntu里既有python2,又有python3,pip就需要著名是pip2,还是pip3。不注明的话,pip就默认的是对应python版本)

  2 from greenlet import greenlet
  3 
  4 
  5 def task1():
  6     while True:
  7         print("---1----")
  8         time.sleep(0.2)
  9         t2.switch()
 10 
 11 
 12 def task2():
 13     while True:
 14         print("---2----")
 15         time.sleep(0.2)
 16         t1.switch()
 17 
 18 
 19 t1=greenlet(task1)
 20 t2=greenlet(task2)
 21 t1.switch()    

执行结果:

wy@ubuntu:~/day1$ python3 f.py
---1----
---2----
---1----
---2----
---1----
---2----
---1----
---2----
---1----
---2----

gevent拿的是greenlet的封装

从结果看,并没有实现多任务,g1执行完之后,再开始执行g2,显然这不是我们想要的。
程序执行到g1=gevent.spawn(task,3)时,并不会立刻执行函数里的代码
g1.join()意思是等待g1全部执行完。

import gevent

def task(n):
    for i in range(n):
        print(gevent.getcurrent(),i)

g1=gevent.spawn(task,3)
g2=gevent.spawn(task,3)
g3=gevent.spawn(task,3)

g1.join()
g2.join()
g3.join()


执行结果:

D:\python\python.exe E:/test1/a.py
<Greenlet at 0x1671190c598: task(3)> 0
<Greenlet at 0x1671190c598: task(3)> 1
<Greenlet at 0x1671190c598: task(3)> 2
<Greenlet at 0x1671190c7b8: task(3)> 0
<Greenlet at 0x1671190c7b8: task(3)> 1
<Greenlet at 0x1671190c7b8: task(3)> 2
<Greenlet at 0x1671190c6a8: task(3)> 0
<Greenlet at 0x1671190c6a8: task(3)> 1
<Greenlet at 0x1671190c6a8: task(3)> 2

进程已结束,退出代码 0
import gevent

def task1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)

def task2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)

def task3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)

g1=gevent.spawn(task1,3)
g2=gevent.spawn(task2,3)
g3=gevent.spawn(task3,3)


g1.join()
g2.join()
g3.join()


执行结果:这样的结果才是我们想要的

D:\python\python.exe E:/test1/a.py
<Greenlet at 0x2171a2dd598: task1(3)> 0
<Greenlet at 0x2171a2dd7b8: task2(3)> 0
<Greenlet at 0x2171a2dd6a8: task3(3)> 0
<Greenlet at 0x2171a2dd598: task1(3)> 1
<Greenlet at 0x2171a2dd7b8: task2(3)> 1
<Greenlet at 0x2171a2dd6a8: task3(3)> 1
<Greenlet at 0x2171a2dd598: task1(3)> 2
<Greenlet at 0x2171a2dd7b8: task2(3)> 2
<Greenlet at 0x2171a2dd6a8: task3(3)> 2

进程已结束,退出代码 0

但是我们平时用的是time.sleep(),想改进的话,需要给程序打补丁:monkey.patch_all()

import gevent
from gevent import monkey
import time

# 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
monkey.patch_all()
def task1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

def task2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

def task3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

g1=gevent.spawn(task1,3)
g2=gevent.spawn(task2,3)
g3=gevent.spawn(task3,3)


g1.join()
g2.join()
g3.join()


执行结果:

D:\python\python.exe E:/test1/a.py
<Greenlet at 0x2434da12158: task1(3)> 0
<Greenlet at 0x2434da12268: task2(3)> 0
<Greenlet at 0x2434da12378: task3(3)> 0
<Greenlet at 0x2434da12158: task1(3)> 1
<Greenlet at 0x2434da12268: task2(3)> 1
<Greenlet at 0x2434da12378: task3(3)> 1
<Greenlet at 0x2434da12158: task1(3)> 2
<Greenlet at 0x2434da12268: task2(3)> 2
<Greenlet at 0x2434da12378: task3(3)> 2

继续改进:

import gevent
from gevent import monkey
import time

# 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
monkey.patch_all()
def task1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

def task2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

def task3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

gevent.joinall([
    gevent.spawn(task1,3),
    gevent.spawn(task2,3),
    gevent.spawn(task3,3)
])

执行结果:

D:\python\python.exe E:/test1/a.py
<Greenlet at 0x1bbba729158: task1(3)> 0
<Greenlet at 0x1bbba729268: task2(3)> 0
<Greenlet at 0x1bbba729378: task3(3)> 0
<Greenlet at 0x1bbba729158: task1(3)> 1
<Greenlet at 0x1bbba729268: task2(3)> 1
<Greenlet at 0x1bbba729378: task3(3)> 1
<Greenlet at 0x1bbba729158: task1(3)> 2
<Greenlet at 0x1bbba729268: task2(3)> 2
<Greenlet at 0x1bbba729378: task3(3)> 2

gevent下载图片实战:

import gevent
from gevent import monkey
import urllib.request

monkey.patch_all()
def downimg(img_name,url):
    ret=urllib.request.urlopen(url)
    content=ret.read()
    with open(img_name,"wb") as f:
        f.write(content)

def main():
    #spawn内的参数是函数名,自定义要保存的图片名以及图片网址
    gevent.joinall([
        gevent.spawn(downimg,"1.jpg","https://rpic.douyucdn.cn/live-cover/roomCover/2019/11/17/c419b278e41b412c1b09c69205efe9c3_big.png/webpdy1"),
        gevent.spawn(downimg,"2.jpg","https://rpic.douyucdn.cn/live-cover/roomCover/2019/11/24/be6d1846edffda51c2deadc979eb2a60_big.jpg/webpdy1"),
    ])


if __name__=="__main__":
    main()

图片下载后保存在项目路径下
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值