异步编程&协程&asyncio
2022/1/14 22:09:07
本文主要是介绍异步编程&协程&asyncio,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
高性能异步爬虫
目的:在爬虫中使用异步实现高性能的数据爬取操作。
异步爬虫的方式:
多进程、多线程: 优点:可以为相关阻塞的操作单独开启线程或者进程,阻塞操作就可以异步执行。 缺点:无法无限制的开启多线程或者多进程。
进程池、线程池: 优点:降低系统对进程或者线程创建和销毁的一个频率,从而很好降低系统的开销。 缺点:池中线程或进程的数量是有上限的。
单线程+异步协程:
event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。 coroutine:协程对象,我们可以讲协程对象注册到事件循环中,它会被事件循环调用。可以使用async关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象。 task:任务。它是对协程对象的进一步封装,包含了任务的各个状态。 future:代表将来执行或还没有执行的任务,实际上和task没有本质区别。 async:定义一个协程。 await:用来挂起阻塞方法的执行。
协程
协程不是计算机提供,程序员人为创造。
协程可以被称为微线程,是一种用户态内的上下文切换技术,简而言之,其实就是通过一个线程实现代码块相互切换执行。例如:
def func1(): print(1) …… print(2) def finc2(): print(3) …… print(4) func1() func2()
greenlet实现协程
from greenlet import greenlet def func1(): print(1) # 第一步:输出 1 gr2.switch() # 第三步:切换到 func2 函数 print(2) # 第六步:输出 2 gr2.switch() # 第七步:切换到func2函数,从上一步执行的位置继续向后执行 def func2(): print(3) gr1.switch() # 第四步:输出 3 print(4) # 第五步:切换到func1 函数,从上一次执行的位置继续向后执行 gr1.switch() # 第八步:输出 4 gr1 = greenlet(func1) gr2 = greenlet(func2) gr1.switch() # 第一步:去执行func1函数
yield关键字
def func1(): yield 1 yield from func2() yield 2 def func2(): yield 3 yield 4 f1 = func1() for item in f1: print(item)
asyncio
python3.4及之后版本
遇到IO阻塞会自动切换
import asyncio @asyncio.coroutine # 原本是个普通函数 加上coroutine可以理解为协程函数 def func1(): print(1) yield from asyncio.sleep(2) # 遇到IO耗时操作,自动化切换到tasks中的其他任务 print(2) @asyncio.coroutine def func2(): print(3) yield from asyncio.sleep(2) # 遇到IO耗时操作,自动化切换到tasks中的其他任务 print(4) tasks = [ asyncio.ensure_future(func1()), asyncio.ensure_future(func2()) ] loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks))# 可以同时执行两个协程函数
async & await关键字
import asyncio async def func1(): print(1) yield from asyncio.sleep(2) # 遇到IO耗时操作,自动化切换到tasks中的其他任务 print(2) async def func2(): print(3) yield from asyncio.sleep(2) # 遇到IO耗时操作,自动化切换到tasks中的其他任务 print(4) tasks = [ asyncio.ensure_future(func1()), asyncio.ensure_future(func2()) ] loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks))# 可以同时执行两个协程函数
普通方式下载图片
import requests def download_image(url): print('开始下载:', url) # 发送网络请求,下载图片 response = requests.get(url) print('下载完成') # 图片保存到本地文件 file_name = url.rsplist('_')[-1] with open(file_name, mode='wb') as file_object: file_object.write(response.content) if __name__ == "__main__": url_list = [ 'https://pic.netbian.com/uploads/allimg/220112/235701-16420030210840.jpg', 'https://pic.netbian.com/uploads/allimg/220112/001807-16419178875bb3.jpg', 'https://pic.netbian.com/uploads/allimg/220111/002539-16418319399169.jpg' ] for item in url_list: download_image(item)
通过协程下载图片
import asyncio import aiohttp import requests 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.rsplist('_')[-1] with open(file_name, mode='wb') as file_object: file_object.write(content) print('下载完成', url) async def main(): async with aiohttp.ClientSession() as session: url_list = [ 'https://pic.netbian.com/uploads/allimg/220112/235701-16420030210840.jpg', 'https://pic.netbian.com/uploads/allimg/220112/001807-16419178875bb3.jpg', 'https://pic.netbian.com/uploads/allimg/220111/002539-16418319399169.jpg' ] tasks = [asyncio.create_task(fetch(session, url)) for url in url_list] await asyncio.wait(tasks) if __name__ == "__main__": asyncio.run(main())
这篇关于异步编程&协程&asyncio的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-12深入理解 ECMAScript 2024 新特性:Map.groupBy() 分组操作
- 2025-01-11国产医疗级心电ECG采集处理模块
- 2025-01-10Rakuten 乐天积分系统从 Cassandra 到 TiDB 的选型与实战
- 2025-01-09CMS内容管理系统是什么?如何选择适合你的平台?
- 2025-01-08CCPM如何缩短项目周期并降低风险?
- 2025-01-08Omnivore 替代品 Readeck 安装与使用教程
- 2025-01-07Cursor 收费太贵?3分钟教你接入超低价 DeepSeek-V3,代码质量逼近 Claude 3.5
- 2025-01-06PingCAP 连续两年入选 Gartner 云数据库管理系统魔力象限“荣誉提及”
- 2025-01-05Easysearch 可搜索快照功能,看这篇就够了
- 2025-01-04BOT+EPC模式在基础设施项目中的应用与优势