目录
4.5.1 相关概念
4.5.2 yield
4.5.3 Greenlet
4.5.4 Gevent
4.5.1 相关概念
目的
单线程下实现并发
概念特性
4.5.2 yield
yield send 得实例
import time def wrapper(func): def inner(*args,**kwargs): ret =func(*args,**kwargs) next(ret) return ret return inner @wrapper def consumer(): while True: x= yield print(x) def producter(target): '''生产者造值''' # next(g) #相当于g.send(None) for i in range(10): time.sleep(0.5) target.send(i)#要用send就得用两个yield producter(consumer())View Code
4.5.3 Greenlet
概念
安装
pip3 install greenlet用法
实例
from greenlet import greenlet import time def eat(name): print('%s eat 1' %name) time.sleep(10) #当遇到IO的时候它也没有切,这就得用gevent了 g2.switch('egon') print('%s eat 2' %name) g2.switch() def play(name): print('%s play 1' %name) g1.switch() print('%s play 2' %name) g1=greenlet(eat) g2=greenlet(play) g1.switch('egon')#可以在第一次switch时传入参数,以后都不需要
4.5.4 Gevent
概念
对程序内部协作式地调度,轻松实现并发同步或异步编程
自动识别 阻塞 ,然后自行切换任务。不在需要手动
安装
pip3 install gevent相关方法
g1=gevent.spawn(func,1,2,3,x=4,y=5) # 创建一个协程对象g1,spawn括号内第一个参数是函数名,后面可以多个参数,可以是位置实参或关键字实参,都是传给函数eat的 g=gevent.spawn(func2) g1.join() #等待g1结束 g2.join() #等待g2结束 #或者上述两步合作一步:gevent.joinall([g1,g2]) gevent.sleep(2) # 模拟的是gevent可以识别的io阻塞 g1.value #拿到func1的返回值 # 当不使用 gevent.sleep(2),使用 time.sleep() 得时候需要导入这个 from gevent import monkey;monkey.patch_all() # 如果不导入直接使用 time.sleep() 会无法实现单线程并发 # 必须放到被打补丁者的前面,如time,socket模块之前实例
基本使用实例
from gevent import monkey;monkey.patch_all() import gevent import time def eat(name): print('%s eat 1' %name) time.sleep(2) print('%s eat 2' %name) return 'eat' def play(name): print('%s play 1' %name) time.sleep(3) print('%s play 2' %name) return 'play' #当有返回值的时候,gevent模块也提供了返回结果的操作 start = time.time() g1 = gevent.spawn(eat,'egon') #执行任务 g2 = gevent.spawn(play,'egon') #g1和g2的参数可以不一样 # g1.join() #等待g1 # g2.join() #等待g2 #上面等待的两句也可以这样写 gevent.joinall([g1,g2]) print('主',time.time()-start) #3.001171588897705 print(g1.value) print(g2.value) """ egon eat 1 egon play 1 egon eat 2 egon play 2 主 3.019590377807617 eat play """View Code爬虫实例
from gevent import monkey;monkey.patch_all() #打补丁 import gevent import requests import time def get_page(url): print('get :%s'%url) response = requests.get(url) if response.status_code==200: #下载成功的状态 print('%d bytes received from:%s'%(len(response.text),url)) start=time.time() gevent.joinall([ gevent.spawn(get_page,'http://www.baidu.com'), gevent.spawn(get_page, 'https://www.yahoo.com/'), gevent.spawn(get_page, 'https://github.com/'), ]) stop = time.time() print('run time is %s' %(stop-start))View Code待回调函数得爬虫实例
from gevent import joinall, spawn, monkey monkey.patch_all() import requests from threading import current_thread def parse_page(res): print('%s PARSE %s' % (current_thread().getName(), len(res))) def get_page(url, callback=parse_page): print('%s GET %s' % (current_thread().getName(), url)) response = requests.get(url) if response.status_code == 200: callback(response.text) if __name__ == '__main__': urls = [ 'https://www.baidu.com', 'https://www.taobao.com', 'https://www.openstack.org', ] tasks = [] for url in urls: tasks.append(spawn(get_page, url)) joinall(tasks) """ DummyThread-1 GET https://www.baidu.com DummyThread-2 GET https://www.taobao.com DummyThread-3 GET https://www.openstack.org DummyThread-1 PARSE 2443 DummyThread-2 PARSE 141762 DummyThread-3 PARSE 65694 """View Code