一个线程多个任务,线程由操作系统开启,比较耗资源。线程内合理分配任务,充分利用线程内的资源,一个任务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())