协程(纤程、轻型线程)
对于操作系统来说,协程是不可见的,不需要操作系统的调度,协程是程序级别的操作单位。
协程的效率高不高和操作系统本身没有关系,不需要操作系统调度,而是看协程的调度合不合理。
协程指的是在同一条线程上能够相互切换多个任务,遇到io就切换实际上是我们利用协程提高线程工作效率的一种方式。
生成器(yield)这种切换就是在一条线程上出现多个任务,着多个任务之间切换本质就是协程,单纯的切换还会浪费时间,但是如果在阻塞的时候切换,并未多个程序的阻塞时间共享,协程就足够大的提高了效率。
协程模块(greenlet) 在多个任务之间来回切换
from greenlet import greenlet
def paly():
print('start play')
g2.switch() #开关
time.sleep(1)
print('end play')
def sleep():
print('start sleep')
time.sleep(1)
print('end sleep')
g1.switch()
g1 = greenlet(play)
g2 = greenelt(sleep)
g1.switch()
gevent模块(基于greenlet实现的,多个任务就交给gevent管理,遇到IO就是用greenlet进行切换)
import time
import gevent
def play():
print('start play')
gevent.sleep(1)
print('end play')
def sleep():
print('start sleep')
print('end sleep')
g1 = gevent.spawn(play)
g2 = gevent.spawn(sleep)
g1.join()
g2.join() #精准的控制协程的任务,join是在等待‘子协程’结束之后立马结束阻塞
# gevent.joinall([g1,g2]) = g1.join()+g2.join()
from gevent import monkey:
monkey.patch_all() #把下面所有的模块中的阻塞都打成一个包,然后gevent就可以识别这些阻塞事件了
协程爬虫
# 协程的爬虫
import time
from urllib.request import urlopen
url_lst = ['https://www.python.org/','https://www.yahoo.com/','https://github.com/']
def get_page(url):
ret = urlopen(url).read()
return ret.decode('utf-8')
start = time.time()
for url in url_lst:
get_page(url)
print(time.time()-start)
from gevent import monkey;monkey.patch_all()
import gevent
url_lst = ['https://www.python.org/','https://www.yahoo.com/','https://github.com/']
def get_page(url):
ret = urlopen(url).read()
return ret.decode('utf-8')
start = time.time()
g_l = []
for url in url_lst:
g = gevent.spawn(get_page,url)
g_l.append(g)
gevent.joinall(g_l)
print(time.time()-start)