1.进程:类Process ;线程:类Thread ;协程:没有定义好的类,只能自己通过定义生成器 yield完成。
协程:耗时操作,包括:网络请求,网络下载(爬虫),IO:文件的读写 阻塞。
一个线程中包含多个协程,只要某个协程出现耗时操作就立即切换到下一协程中
2.基于生成器执行任务:
# 生成器
import time
def task1():
for i in range(3):
print('A' + str(i))
yield
time.sleep(1)
def task2():
for i in range(3):
print('B' + str(i))
yield
time.sleep(2)
if __name__ == '__main__':
ga = task1()
gb = task2()
while True:
try:
next(ga)
next(gb)
except:
break
输出结果:
3.使用基于生成器的包(greenlet)调用协程执行任务
# greenlet
import time
from greenlet import greenlet
def a(): # 任务A
for i in range(5):
print('A' + str(i))
gb.switch()
time.sleep(0.1)
def b(): # 任务B
for i in range(5):
print('B' + str(i))
gc.switch()
time.sleep(0.1)
def c(): # 任务C
for i in range(5):
print('C'+str(i))
ga.switch()
time.sleep(0.1)
if __name__ == '__main__':
ga = greenlet(a)
gb = greenlet(b)
gc = greenlet(c)
ga.switch()
输出结果:
4.使用gevent模块可以自动切换任务,其原理是当一个greenlet遇到IO(指的是input output输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO完成,在适当的时候切换回来继续执行。
# 案例
import urllib.request
import gevent
from gevent import monkey
monkey.patch_all()
def download(url):
response = urllib.request.urlopen(url)
content = response.read()
print('下载了{}的数据,长度:{}'.format(url, len(content)))
if __name__ == '__main__':
urls = ['http://www.163.com', 'http://www.qq.com', 'http://www.baidu.com']
g1 = gevent.spawn(download, urls[0])
g2 = gevent.spawn(download, urls[1])
g3 = gevent.spawn(download, urls[2])
gevent.joinall([g1, g2, g3])
输出结果:
感谢哔站上千峰教育提供的python学习视频!