协程
- 使用
- 方法一
- 方法二
- 网页下载中使用
- 有返回值
- 实战
- 图片实战
一个线程多个任务,线程由操作系统开启,比较耗资源。线程内合理分配任务,充分利用线程内的资源,一个任务io阻塞时,cpu处理其他非阻塞任务。
使用
方法一
import asyncio
# 函数前加async后,成为协程对象
async def as_func():print('协程基本使用')
if __name__ == '__main__':# 1 创建一个协程对象async_obj = as_func()print(async_obj)# 2 创建事件循环event_loop = asyncio.get_event_loop()# 3 执行协程对象event_loop.run_until_complete(async_obj)
方法二
- 可能报RuntimeError: Event loop is closed
import asyncio
# 函数前加async后,成为协程对象
async def as_func():print('协程基本使用')
if __name__ == '__main__':# 1 创建一个协程对象async_obj = as_func()print(async_obj)# 2 执行协程asyncio.run(async_obj)
网页下载中使用
import asyncio
# 函数前加async后,成为协程对象
async def as_download(url, t):print(url + '协程下载')await asyncio.sleep(t)print(url + '下载完成')async def main():urls = ['url1','url2','url3','url4',]as_tasks = []for url in urls:as_task = asyncio.create_task(as_download(url, 2))as_tasks.append(as_task)await asyncio.wait(as_tasks)if __name__ == '__main__':asyncio.run(main())
有返回值
- wait和gather
import asyncio
async def as_download1():print("协程1开始")await asyncio.sleep(1)print("协程1完成")return "协程1返回"
async def as_download2():print("协程2开始")await asyncio.sleep(2)print("协程2完成")return "协程2返回"
async def as_download3():print("协程3开始")await asyncio.sleep(3)print("协程3完成")return "协程3返回"
async def main():tasks = [asyncio.create_task(as_download3()),asyncio.create_task(as_download1()),asyncio.create_task(as_download2()),]# 取返回值一, wait, 返回的结果是set集合,无序result, pending = await asyncio.wait(tasks)for res in result:print(res.result())print("--以上是随机顺序--"*3)print("--以下是与任务相同顺序--"*3)# 取返回值二, gather, 同map一样,返回的结果的顺序与任务顺序一致# return_exceptions=True,即使有错误,任务正常执行,返回错误信息# return_exceptions=False,如果有错误,程序报错,任务停止result = await asyncio.gather(*tasks, return_exceptions=True)for res in result:print(res)
if __name__ == '__main__':asyncio.run(main())
实战
- aiohttp和aiofiles安装
pip install aiohttp
pip install aiofiles
图片实战
链接: url_list
链接: url_list
链接: url_list
import aiohttp
import asyncio
import aiofiles
async def pic_download(url):try:name = url.split("/")[-1]# 创建session对象 with使用完后自行关闭async with aiohttp.ClientSession() as session:# 发送请求url请求async with session.get(url) as resp:# content.read()读取图片数据# resp.text()读取源代码即可content = await resp.content.read()# 写入文件会阻塞, 用aiofiles提升效率async with aiofiles.open(name, mode="wb") as f:await f.write(content)return "finish complete"except:print('报错')return "failure"
async def main():url_list = ["","","","","",]tasks = []for url in url_list:# 创建任务task = asyncio.create_task(pic_download(url))tasks.append(task)await asyncio.wait(tasks)
if __name__ == '__main__':# asyncio.run(main()) 此句与下2句等同,但在一些版本中报错loop = asyncio.get_event_loop()loop.run_until_complete(main())