前言
协程:本质上是一个线程能够在多个任务之间切换来节省一些IO时间;
协程中任务之间的切换也消耗时间,但是开销要远远小于进程线程之间的切换;既是协程任务之间可以通过代码调度切换(但只有协程模块能识别的IO操作才能实现效果)
一、初识协程
1、greenlet例子:
执行A函数切换至B函数执行后,又切换回A函数。一般编程高并发用:进程+线程+协程
# 一、初识协程:greenlet例子 # 执行A函数切换至B函数执行后,又切换回A函数。一般编程高并发用:进程+线程+协程 from greenlet import greenlet def func(): print('func_start') r2.switch() # 切换到r2,并记录func函数的执行到的位置 print('func_end') def func1(): print('func1_start') r1.switch() # 切换到r1,所以最后会打印func_end print('func1_end') r1=greenlet(func) r2=greenlet(func1) r1.switch()
2、gevent:协程
按正常执行结果会是函数A结束,再运行函数B,但在协程中能够在函数之间切换。
from gevent import monkey;monkey.patch_all() 必须写上,最后直接写在导入模块前,否则不可识别起不到效果。
from gevent import monkey;monkey.patch_all() import gevent import time def func(): print('func_start') time.sleep(1) # 只能导入:monkey;monkey.patch_all() 才能感知 # gevent.sleep(1) # 否则用自己的模块的等待 print('func_end') def func1(): print('func1_start') time.sleep(1) # gevent.sleep(1) print('func1_end') r1=gevent.spawn(func) # 起一个协程任务 r2=gevent.spawn(func1) # 起一个协程任务 r1.join() # 执行 r2.join() # 执行
3、同步与异步
# 3、同步与异步 from gevent import monkey;monkey.patch_all() import gevent import time def func(): time.sleep(1) print(666) def sync(): # 同步 for i in range(2): func() def async(): # 异步 g_lst=[] for i in range(5): g=gevent.spawn(func) g_lst.append(g) gevent.joinall(g_lst) sync() async()
4、简单爬虫实例
①正常写法,没有协程:
消耗的时间: 2.069894790649414
import requests,time s=requests.session() def get_len(url): r=s.get(url) return len(r.text) urls=['https://www.cnblogs.com/gsxl/','http://news.baidu.com/','https://www.baidu.com/', 'https://daohang.qq.com/?fr=hmpage','https://www.csdn.net/'] start=time.time() for url in urls: r=get_len(url) print(r) t1=time.time()-start print('时间:',t1)
②运用协程:gevent
消耗的时间:1.0143725872039795
# ②运用协程:gevent from gevent import monkey;monkey.patch_all() import requests,time import gevent s=requests.session() def get_len(url): r=s.get(url) return len(r.text) urls=['https://www.cnblogs.com/gsxl/','http://news.baidu.com/','https://www.baidu.com/', 'https://daohang.qq.com/?fr=hmpage','https://www.csdn.net/'] r_lst=[] start=time.time() for url in urls: r=gevent.spawn(get_len,url) r_lst.append(r) gevent.joinall(r_lst) for i in r_lst: print(i.value) t1=time.time()-start print(t1
小结:
- 进程和线程的任务切换是操作系统调度
- 协程任务之间可以通过代码调度切换(但只有协程模块能识别的IO操作才能实现效果)
欢迎来大家QQ交流群一起学习:482713805