一、什么是协程
满足下列条件的可以说是协程(摘抄):
1.必须在只有一个单线程里实现并发
2.修改共享数据不需加锁
3.用户程序里自己保存多个控制流的上下文栈
4.一个协程遇到IO操作自动切换到其它协程
二、实现协程
1.调用C中的greenlet包实现协程
代码案例使用方法列表:
from greenlet import greenlet #导入扩展包
.switch() #切换运行对象
greenlet(<方法名>) #创建对象,指定目标方法
代码案例:
from greenlet import greenlet
def function1():
print('第一步')
gre2.switch() #转到第二步
print('第三步')
gre2.switch() #转到第四步
def function2():
print('第二步')
gre1.switch() #转到第三步
print('第四步')
gre1 = greenlet(function1) #创建greenlet对象
gre2 = greenlet(function2)
gre1.switch()
输出:
第一步
第二步
第三步
第四步
2.第三方库 Gevent
Gevent: 基于协程的python网络库,以C扩展模块形式接入Python的轻量级协程
代码案例方法运用列表:
gevent.joinall([]) #添加gevent对象
gevent.spawn(<方法>,<参数>) #创建gevent对象
gevent.sleep() #单线程调节语句,与time.time()不同
①.Gevent:代码案例:
import gevent,time
def function1(name):
print('????,%s'%name)
gevent.sleep(2)
print('!!!!')
def function2():
print('$$$$')
gevent.sleep(1)
print('&&&&')
start = time.time()
gevent.joinall([
gevent.spawn(function1,'啊这?'),
gevent.spawn(function2)
])
end = time.time()
print('time :%s'%(end-start))
输出案例:
????,啊这?
$$$$
&&&&
!!!!
time :2.0344367027282715
②.Gevent:代码案例(网页数据爬取案例):
import gevent,time
from urllib.request import urlopen
from gevent import monkey
monkey.patch_all() #更有效的捕捉IO阻塞的补丁
def f(u):
urlopen(u)
#Gevent方法
start = time.time()
gevent.joinall([
gevent.spawn(f, 'https://www.python.org/'),
gevent.spawn(f, 'https://marketing.csdn.net/'),
gevent.spawn(f, 'http://news.baidu.com/')
])
end = time.time()
print('gevent: %s'%(end-start))
#普通方法
start2 = time.time()
gevent_list =['https://www.python.org/','https://marketing.csdn.net/','http://news.baidu.com/']
for u in gevent_list:
f(u)
end2 = time.time()
print('普通: %s'%(end2-start2))
输出:
gevent: 0.46442246437072754
普通: 0.8198473453521729