协程的简单使用
定义:协程:又称为微线程,也可以说成用户级线程, 在不开辟线程的基础上可以完成多任务
特征: 如何理解协程: 只要在def里面只看到一个yield关键字表示就是协程,在单线程的基础上可以完成多任务,多个任务按照一定顺序交替执行.
import time
# 协程1
def work1():
while True:
print("work1....")
time.sleep(0.2)
yield
# 协程2
def work2():
while True:
print("work2....")
time.sleep(0.2)
yield
if __name__ == '__main__':
# 创建协程对象
g1 = work1()
g2 = work2()
while True:
# 启动协程
next(g1)
next(g2)
greenlet 的使用(补充 实际中很少使用)
greenlet: 为了更好的让程序员使用协程可以使用greenlet,因为greent封装的yield
# 创建协程执行对应的任务
g1 = greenlet.greenlet(work1)
g2 = greenlet.greenlet(work2)
# 切换到第一个协程执行对应的任务
g1.switch()
gevent 的使用(实际中用这个)
gevent : gevent框架封装Greenlet,会根据耗时操作自动完成协程之间的切换执行
gevent 的实际案例 并发下载 网页图片
import urllib.request # 导入网络请求模块
import gevent
from gevent import monkey
# 打补丁,让gevnet能够识别网络请求的耗时操作,完成协程之间的自动切换执行
monkey.patch_all()
# 下载图片的任务函数
def download_img(img_url, img_name):
try:
# 根据图片地址加载网络资源数据
response = urllib.request.urlopen(img_url)
# 读取网络中的资源数据, 考虑到图片文件有可能比较大,然后循环读取数据
# 打开文件写入对应图片数据
with open(img_name, "wb") as img_file:
while True:
# 读取网络数据
img_data = response.read(1024)
if img_data:
# 把图片二进制数据写入到指定图片文件里面
img_file.write(img_data)
else:
break
except Exception as e:
print("图片下载出现异常:", e)
else:
print("%s图片下载成功" % img_name)
if __name__ == '__main__':
# 准备图片地址
img_url1 = "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3722615040,3422677914&fm=27&gp=0.jpg"
img_url2 = "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1815077192,817368579&fm=27&gp=0.jpg"
img_url3 = "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1073392760,440995056&fm=27&gp=0.jpg"
# 创建协程对象指定对应的任务
# 1. 函数名
# 2. 函数对应的参数1: img_url2,
# 3. 函数对应的参数2: 图片名
g1 = gevent.spawn(download_img, img_url1, "1.jpg")
g2 = gevent.spawn(download_img, img_url2, "2.jpg")
g3 = gevent.spawn(download_img, img_url3, "3.jpg")
# 主线程等待所有的协程执行完成以后程序再退出
gevent.joinall([g1, g2, g3])
网友评论