文章目录
1、协程
1、定义:微线程,人为创造协程,控制程序上下文切换执行流程,一个线程中只能有一个协程
2、python实现协程:
1、yield && yield from
2、asyncio模块
3、gevent模块
2、asyncio模块
版本python3.5以上
1、事件循环–asyncio.get_event_loop()
检测并执行某些代码
import asyncio
# 生成一个事件循环
loop = asyncio.get_event_loop()
# 将任务放到‘任务列表’
loop.run_untik_complate(任务)
asyncio.run()
内部先创建事件循环,在将任务放到任务列表执行
2、await
await+可等待的对象(协程对象、future、task对象)
import asyncio
async def start_run():
print('开始运行start run')
await asyncio.sleep(2)
print('结束运行 end')
return '返回值'
coroutine=start_run()
# start_run()返回一个协程对象
asyncio.run(coroutine)
await 等待对象执行结果结束之后再继续执行
await遇到io操作切换到其他任务
3、task对象
在事件循环中并发添加多个任务
asyncio.create_task(协程对象)
asyncio.ensure_future(协程对象)
使用以上方法创建协程对象后,会将函数添加到事件循环中
import asyncio
async def start_run():
print('开始运行start run')
await asyncio.sleep(2)
print('结束运行 end')
return '返回值'
async def main():
task_list = [
asyncio.create_task(start_run()),
asyncio.create_task(start_run())
]
done,pending = await asyncio.wait(task_list,timeout=None)
print(done)
print(pending)
if __name__ == '__main__':
asyncio.run(main())
4、future对象
task继承future对象,task对象结果处理基于future
import asyncio
async def set_result(fnt):
# io操作
await asyncio.sleep(2)
#设置协程返回结果
fnt.set_result('result')
async def main():
# 获取当前事件循环对象
loop = asyncio.get_running_loop()
print(loop)
# 创建future对象
fu = loop.create_future()
print(type(fu))
await loop.create_task(set_result(fu))
res = await fu
print(res)
asyncio.run(main())
案例:异步下载图片
import asyncio,requests
async def download_image(url):
print('开始下载:',url)
loop = asyncio.get_event_loop()
# 可使用以下替换默认线程池为ThreadPoolExecutor
# exe = ThreadPoolExecutor(2)
# asyncio.get_event_loop().set_default_executor(exe)
# 使用loop中带的线程池实现
future_loop = loop.run_in_executor(None,requests.get,url,{"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"})
response = await future_loop
print('下载完成')
# 保存
filename = url.split('_')[-1]
with open(filename,mode='wb') as file_obj:
file_obj.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'
]
tasks = [download_image(url) for url in url_list]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))