**协程(微线程,纤程):可以暂停执行的函数,就行生成器一样
线程和进程的操作是由程序触发系统接口,最后的执行者是系统,协程的操作是程序员
意义:多线程应用,cpu通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)
协程,则只使用一个线程(单线程),在一个线程中规定某个代码块执行顺序
使用:不需要cpu的操作(IO)**
yield 协程的简单实现-一个线程完成两个任务
def work1():
while True:
print("正在执行work1.....")
yield
time.sleep(0.5)
def work2():
while True:
print("正在执行work2.....")
yield
time.sleep(0.5)
if __name__ == '__main__':
w1 = work1()
w2 = work2()
while True:
next(w1)
next(w2)
greenlet 实现协程,程序员手动控制
def greenletWork1(*args):
print("正在执行greenletwork1.....", args)
time.sleep(0.5)
# 切换到第二个任务
g_w2_data = g_w2.switch(name="cg", id="110")
print("g_w2_data", g_w2_data)
def greenletWork2(**kwargs):
print("正在执行greenletwork2.....", kwargs)
time.sleep(0.5)
# 切换到第一个任务
g_w1.switch(1, 2, 3)
if __name__ == '__main__':
g_w1 = greenlet.greenlet(greenletWork1)
g_w2 = greenlet.greenlet(greenletWork2)
# 执行work1
g_w1.switch(4, 5, 6)
gevent 实现协程,自动识别耗时操作
from gevent import monkey
#破解所有:
monkey.patch_all()
def geventWork1(*args):
print("正在执行geventWork1.....", args, "协程标识:", gevent.getcurrent())
# gevent 不认为time.sleep()是耗时操作
# 1.换成gevent.sleep()
# 2.打补丁,在不修改程序源代码的情况下,为程序增加新功能
time.sleep(5)
# gevent.sleep(5)
# 打补丁,一般放开头处
# from gevent import monkey
# 破解所有:monkey.patch_all()
"""
1.在运行时替换方法、属性等
2.在不修改第三方代码的情况下增加原来不支持的功能
3.在运行时为内存中的对象增加patch而不是在硬盘的源代码中增加
"""
print("geventWork1运行结束。。。。。")
def geventWork2(**kwargs):
print("正在执行geventWork2.....", kwargs, "协程标识:", gevent.getcurrent())
gevent.sleep(5)
print("geventWork2运行结束。。。。。")
if __name__ == '__main__':
gevent_work1 = gevent.spawn(geventWork1, 1, 2, 3)
gevent_work2 = gevent.spawn(geventWork2, name="cg", age=18)
# 让主线程等待协程完成再结束
gevent_work1.join()
gevent_work2.join()
案例:并发下载器
import urllib.request
import gevent
def download_img(imgUrl, fileName):
# 根据url地址获取网络资源
try:
response_data = urllib.request.urlopen(imgUrl)
with open(fileName, "wb") as file:
while True:
file_data = response_data.read(1024)
if file_data:
file.write(file_data)
else:
break
except BaseException as error:
print("文件下载失败", fileName)
else:
print("下载成功", fileName)
if __name__ == '__main__':
img_url1 = "https://p1.itc.cn/images01/20211020/89006406f0174e0dafba430f5301b212.gif"
img_url2 = "https://p8.itc.cn/images01/20211020/42bfd49d7a6a4d809ab2b4190b4afa72.gif"
img_url3 = "https://p0.itc.cn/images01/20211020/a7f05e4e306342b3a7eadc412515c3ff.gif"
gevent.joinall([
gevent.spawn(download_img,img_url1,"1.gif"),
gevent.spawn(download_img,img_url2,"2.gif"),
gevent.spawn(download_img,img_url3,"3.gif")
])