2.协程的意义
通过学习,我们已经了解到协程可以通过一个线程在多个上下文中进行来回切换执行。
但是,协程来回切换执行的意义何在呢?(网上看到很多文章舔协程,协程牛逼之处是哪里呢?)
计算型的操作,利用协程来回切换执行,没有任何意义,来回切换并保存状态 反倒会降低性能。
IO型的操作,利用协程在IO等待时间就去切换执行其他任务,当IO操作结束后再自动回调,那么就会大大节省资源并提供性能,从而实现异步编程(不等待任务结束就可以去执行其他代码)。
2.1 爬虫案例
例如:用代码实现下载 url_list
中的图片。
-
方式一:同步编程实现
""" 下载图片使用第三方模块requests,请提前安装:pip3 install requests """ import requests def download_image(url): print("开始下载:",url) # 发送网络请求,下载图片 response = requests.get(url) print("下载完成") # 图片保存到本地文件 file_name = url.rsplit('_')[-1] with open(file_name, mode='wb') as file_object: file_object.write(response.content) if __name__ == '__main__': url_list = [ 'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg', 'https://www2.autoimg.cn/newsdfs/g30/M01/3C/E2/120x90_0_autohomecar__ChcCSV2BBICAUntfAADjJFd6800429.jpg', 'https://www3.autoimg.cn/newsdfs/g26/M0B/3C/65/120x90_0_autohomecar__ChcCP12BFCmAIO83AAGq7vK0sGY193.jpg' ] for item in url_list: download_image(item)
-
方式二:基于协程的异步编程实现
""" 下载图片使用第三方模块aiohttp,请提前安装:pip3 install aiohttp """ #!/usr/bin/env python # -*- coding:utf-8 -*- import aiohttp import asyncio async def fetch(session, url): print("发送请求:", url) async with session.get(url, verify_ssl=False) as response: content = await response.content.read() file_name = url.rsplit('_')[-1] with open(file_name, mode='wb') as file_object: file_object.write(content) async def main(): async with aiohttp.ClientSession() as session: url_list = [ 'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg', 'https://www2.autoimg.cn/newsdfs/g30/M01/3C/E2/120x90_0_autohomecar__ChcCSV2BBICAUntfAADjJFd6800429.jpg', 'https://www3.autoimg.cn/newsdfs/g26/M0B/3C/65/120x90_0_autohomecar__ChcCP12BFCmAIO83AAGq7vK0sGY193.jpg' ] tasks = [asyncio.create_task(fetch(session, url)) for url in url_list] await asyncio.wait(tasks) if __name__ == '__main__': asyncio.run(main())
上述两种的执行对比之后会发现,基于协程的异步编程
要比 同步编程
的效率高了很多。因为:
- 同步编程,按照顺序逐一排队执行,如果图片下载时间为2分钟,那么全部执行完则需要6分钟。
- 异步编程,几乎同时发出了3个下载任务的请求(遇到IO请求自动切换去发送其他任务请求),如果图片下载时间为2分钟,那么全部执行完毕也大概需要2分钟左右就可以了。
2.2 小结
协程一般应用在有IO操作的程序中,因为协程可以利用IO等待的时间去执行一些其他的代码,从而提升代码执行效率。
生活中不也是这样的么,假设 你是一家制造汽车的老板,员工点击设备的【开始】按钮之后,在设备前需等待30分钟,然后点击【结束】按钮,此时作为老板的你一定希望这个员工在等待的那30分钟的时间去做点其他的工作。