协程:
gevent -协程
当多线程和多进程都无法实现客户需求的时候,协程就出现了
协程的使用过程
1、协程的导入
import gevent#没有这个库就取pip下载
2、声明需要执行的函数
def f1():
...
3、协程对象的实例化
g1 = gevent.spawn(f1,5)#f1是需要协程执行的函数,第二个是需要传输的参数
测试案例:
import gevent#导入
def work1(n):#执行的函数
for i in range(n):
print(gevent.getcurrent(),i)#打印当前的协程号
gevent.sleep(0.4)#协程体现
def work2(n):
for i in range(n):
print(gevent.getcurrent(),i)
gevent.sleep(0.4)
def work3(n):
for i in range(n):
print(gevent.getcurrent(),i)
gevent.sleep(0.4)
print('----start----')
g1 = gevent.spawn(work1, 5)#创建协程对象
g2 = gevent.spawn(work2, 5)
g3 = gevent.spawn(work3, 5)
g1.join()#执行协程
g2.join()
g3.join()
协程实现爬取图片:
#协程实现图片下载
import requests
import gevent
from lxml import etree
def download_imgs(args):#参数是图片的url
img_url, save_path = args
response = requests.get(img_url)
img = response.content
with open(save_path+'//'+img_url[-6:],'wb') as f:
f.write(img)
def main():
#1获取图片的urls
url = 'https://www.huya.com/g/2168'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36'
}
response = requests.get(url,headers=headers).text
html = etree.HTML(response)
urls = html.xpath("//img[@class='pic']/@data-original")
new_urls = []
for url in urls:#将图尾部表示大小的部分qudiao
new_urls.append(url.split('?')[0])
#2创建多个协程
#保存图片的地址
save_path = input('输入要保存的地址')
for new_url in new_urls:
g = gevent.spawn(download_imgs,(new_url,save_path))
g.join()
#3保存图片
if __name__ == '__main__':
main()
总结:
1、协程是其他函数在停滞不前的时候(例如sleep)利用这个时间取执行别的任务
2、一次可以执行多个协程而不是g1,g1这样分开写gevent.joinall([gevent.spawn(f1,args),genent.spawn(f2,args)…])
线程,进程,协程大对比
1、进程是资源分配的单位
2、线程是操作系统调度单位
3、进程耗费大量资源,效率低
4、线程耗费资源一般,效率一般
5、协程切换任务资源很小,效率高
6、协程是并发的,进程和线程根据CPU和数不一定是并发的