系列文章目录
- 使用greenlet,gevent完成多任务
一、使用greenlet,gevent完成多任务
这里要先在pycharm里面提前安装好greenlet和gevent的包
操作:
代码:
from greenlet import greenlet
import time
def test1():
while True:
print("--a--")
gr2.switch()
time.sleep(0.5)
def test2():
while True:
print("--b--")
gr1.switch()
time.sleep(0.5)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
# 切换gr1中运行
gr1.switch()
运行结果:
这里的greenlet比yield实现起来还要更简单一点
下面是使用的gevent,这个是用的比较多的一种,功能更强大
其原理是当一个greenlet遇到io(指的是input output 输入输出时,比如网络,文件操作等),比如访问网络,就自动切换到其他的greenlet,等到io操作完成,再在适当的时候切换回来继续执行。由于io操作相当耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待io
操作:
这里通过spawn创建一个对象,其实就是greenlet,第一个参数是指定将来要执行任务的名字,第二个参数如果有的话就可以传递,没有的话可以不写
输出结果:
如果要验证这个是否是多任务的话,使用gevent.sleep就可以
输出结果:
最后控制台输出的时候,是一次输出三个结果的
案例:做一个图片下载器
现在浏览器找一个图片
举例:在网上找一个图片
鼠标右键单击,下面有一个审查元素,再点击一下这个小箭头,后面鼠标停在哪一个图片上,右边的小窗口就会跟上
我这里选择的是这个老虎,把箭头指向的这一串网址复制下来,右键选择copy,copy element。复制好了,单独粘贴到一个文件里,在选择这一串网址
操作:
最后点开查看就行:
同样也是可以爬视频的
上面只是简单的爬一张照片,接下来就是用gevent同时爬多张图片
下面是同时下载两个的操作:
代码:
import urllib.request
import gevent
from gevent import monkey
monkey.patch_all()
def down_loader(image_name, img_url):
req = urllib.request.urlopen(img_url)
img_contend = req.read()
with open(image_name, "wb") as f:
f.write(img_contend)
def main():
gevent.joinall([
gevent.spawn(down_loader, "2.jpg", "https://p0.ssl.qhimgs1.com/sdr/400__/t01a3829bbb034da41e.jpg"),
gevent.spawn(down_loader, "3.jpg", "https://p0.ssl.qhimgs1.com/sdr/400__/t01a55368c03c6ba28a.jpg")
])
if __name__ == "__main__":
main()
要下载更过的话,望joinall里面扔网址就行了
总结
最后总结一下进程,线程,协程对比
- 进程是资源分配的单位
- 线程是操作系统调度的单位
- 进程切换需要的资源很大,效率很低
- 线程切换需要的资源一般,效率一般(当前在不考虑GIL的情况下,后续会说的)
- 协程切换任务资源很小,效率高
- 多进程,多线程根据cup核数不一样,可能是并行的,但是协程是在一个线程中,所以是并发的