前言
线程和进程都是抢占式是使用cpu资源,协程是非抢占式的使用cpu资源,可以认为的去指定程序去使用cpu资源。协程不通过线程而实现程序的并发。但是协程只能在一个进程中执行,无法使用多核,因此多进程+协程是一种很好的方案
通过使用yield来模拟线程间切换数据的保存
#这是一个生成器 def consumer(name): print("--->ready to eat baozi...") while True: new_baozi = yield print("[%s] is eating baozi %s" % (name,new_baozi)) #time.sleep(1) def producer(): r = con.__next__() #consumer对象在yield处挂住,等待传值赋值给new_baozi r = con2.__next__() #consumer对象在yield处挂住,等待传值赋值给new_baozi n = 0 while 1: time.sleep(1) print("\033[32;1m[producer]\033[0m is making baozi %s and %s" %(n,n+1) ) con.send(n) #发送数据给yield,将值赋值给new_baozi con2.send(n+1) #发送数据给yield,将值赋值给new_baozi n +=2 if __name__ == '__main__': con = consumer("c1") con2 = consumer("c2") producer() ############################### --->ready to eat baozi... --->ready to eat baozi... [producer] is making baozi 0 and 1 [c1] is eating baozi 0 [c2] is eating baozi 1 [producer] is making baozi 2 and 3 [c1] is eating baozi 2 [c2] is eating baozi 3 [producer] is making baozi 4 and 5 [c1] is eating baozi 4 [c2] is eating baozi 5 [producer] is making baozi 6 and 7 [c1] is eating baozi 6 [c2] is eating baozi 7 ......
greenlet模块
from greenlet import greenlet
def test1():
print(12)
gr2.switch() #切换到test2()处
print(34)
def test2():
print(56)
gr1.switch() #切换到test1()处
print(78)
gr1.switch() #切换到test1()处
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr2.switch() #切换到test2()处
###################
56
12
78
34
gevent模块
import gevent
import requests,time
def f(url):
print('GET: %s' % url)
resp =requests.get(url) #爬取网站
data = resp.text
print('%d bytes received from %s.' % (len(data), url))
#5个爬取操作进行协程的操作
gevent.joinall([
gevent.spawn(f, 'https://www.python.org/'), #f是函数名,后面是参数
gevent.spawn(f, 'https://www.yahoo.com/'),
gevent.spawn(f, 'https://www.baidu.com/'),
gevent.spawn(f, 'https://www.sina.com.cn/'),
gevent.spawn(f, 'http://www.xiaohuar.com/hua/'),
])
通过协程的方式进行爬取网站要比串行的方式进行爬取网站要快,爬取的内容越多,差别越大