async方式实现异步并发,以下讲解的使用方式仅支持python3.7及以上版本,每个版本均更新了异步的不同的使用方法,大家感兴趣的可以去了解下。
所谓异步,就是程序执行一个协程任务,遇到协程任务需要等待的,且等待无需占用程序资源,程序可以继续执行其他的代码情况下,无需等待协程任务执行完毕,程序可挂起该协程任务,继续执行下一个协程任务,待被挂起的任务等待时间到,则程序返回继续执行该任务。什么是协程呢?这里大家通俗理解成线程中的代码片段吧。这里就不展开解释,接下来主要讲async/await的理解及如何简单使用。
以下是自己的简单整理的思路,只是简单入门下如何使用,并未深入,如有错误,欢迎指正。如果想要深入学习,推荐带大家看这篇文章,异步编程的前因后果都讲的非常清楚。
深入理解Python异步编程(上) (qq.com)
安装
pip install asyncio
用法
关键字async关键字声明执行的函数是协程块
使用async关键字封装函数有何用呢?如果不封装是否有何影响?
通常函数的执行是,从头执行到尾,遇到return就退出。使用async关键字声明的函数,则会返回一个协程对象,在await关键字声明处中断,暂时挂起,去执行其他的函数,后续再返回继续执行。这里只是使用关键字async定义协程,函数单独执行的话,内部的内容并不会执行,而是返回协程对象,函数的运行还是需要借助事件循环去执行。
await关键字需要在哪些地方使用呢?
await关键字只能在async关键字修饰的函数内使用。 语法:await声明可等待对象 这里的对象只能是异步的程序或者是有__await__属性的对象。 表示对象主动让出执行权,暂时挂起,这里的对象是协程,表示协程暂时挂起,等待返回结果。
async def func():
# 声明程序可以让出执行权的地方,也就是无需占用资源一直等待的地方
await asyncio.sleep(等待时间)
创建事件循环,封装函数为协程任务,协程将会被自动调度
通过asyncio.create_task()创建协程任务,返回协程对象,同时create_task方法会将协程对象注册到事件循环中,通过loop异步调用协程对象运行,保存协程运行状态,方便获取每个协程的执行结果
执行协程任务对象时,遇到await则挂起协程任务,从而执行下一个协程任务
async def main():
tasks = [
asyncio.create_task(func),
aysncio.creat_task(func),
...]
await asyncio.wait(tasks)
通过run执行协程任务
run函数会监听main函数,直到main函数执行完毕后,才会结束事件循环
# 该方式在python3.7及以上版本才可使用
asyncio.run(main())
例子
例子共执行2个任务,任务1执行等待时间需要1s,任务2执行等待时间需要2s,按顺序执行共等待3s,异步执行则需要2s。
import time
import asyncio
# async声明函数say_after为协程对象
async def say_after(delay, what,name):
# 步骤5:还未遇到await关键字,则正常执行任务1的代码
# 步骤7:还未遇到await关键字,则正常执行任务2的代码
print(f"开始执行{name}不让出执行权的代码")
print(f"这是{name}正常执行的代码")
# 步骤6:遇到await关键字,则表示任务1让出执行权,继续执行下一个协程任务对象任务2
# 直到协程任务1对象的等待时间1s到了,再返回继续执行任务1
# 步骤8:遇到await关键字,则表示任务2让出执行权,继续执行下一个协程任务对象
await asyncio.sleep(delay)
# 步骤9:由于这里只有2个协程任务对象,没有下一个,协程任务1等待的1s时间到
# 执行协程任务1等待时间到了后面需要执行的代码,同时协程任务2的等待时间也过去了1s
# 步骤10:协程任务2等待的2s时间到,开始执行后面的代码
print(f"{name}执行时间:{time.strftime('%X')}")
print(f"这是协程任务等待时间到了后需要执行的代码:{what}")
async def main():
# 步骤2:2.1 创建协程任务task1,task2,此时已同步将协程任务注册到事件循环中,返回协程可执行任务,等待执行
# 2.2 task1,task2协程函数调用后并不会执行函数内部
# 2.3 此时每个任务的状态是pending,准备状态还未被执行
for i in range(2):
tasks = asyncio.create_task(
say_after(i+1, f'内容{i+1}',name=f"任务{i+1}"))
# 步骤3:打印开始执行时间
print(f"所有协程任务开始执行前的时间:{time.strftime('%X')}")
# 步骤4:声明tasks是可等待对象,执行协程任务
await tasks
# 步骤11:打印执行结束时间,最终执行结束即开始执行时间+最大的协程任务等待时间
# 也就是task2协程任务的等待时间2s
# 步骤12:结束执行时间
print(f"所有协程任务最后执行前的时间:{time.strftime('%X')}")
# 步骤1:执行协程调度函数
asyncio.run(main())
aiohttp
aiohttp简介
若是想要实现并发http请求,那么就需要来认识下aiohttp。
aiohttp是asyncio和Python的异步HTTP客户端/服务器,aiohttp可以实现单线程并发IO操作。这里我们主要讲客户端发送请求的使用,服务端暂时不讲。
用法
创建session对象
通过aiohttp.ClientSession()创建一个客户端会话session
async with aiohttp.ClientSession() as session:
.....
使用session对象请求网页
async with aiohttp.ClientSession() as session:
# session.get可修改为对应的请求方式,并添加对应的参数,如post请求,添加data的参数
async with session.get('请求url') as resp:
........
关键字async关封装执行的函数
async def func():
async with aiohttp.ClientSession() as session:
async with session.get('请求url') as resp:
.....
await session.close()
主函数创建任务,协程调度执行任务
async def main():
for i in range(并发次数):
task = asyncio.create_task(func())
await task
....
执行主函数
asyncio.run(main())
例子
例子共并发2个请求百度的任务,每个任务等待2s,顺序执行则需要4s,采用异步的方式,最终的执行时间仅需要2s。
import time
import asyncio
import aiohttp
import json
# async声明函数say_after为协程对象
async def get_https():
async with aiohttp.ClientSession() as session:
async with session.get(https://www.baidu.com) as resp:
# 假设这里有请求网页后等待响应的时间
await asyncio.sleep(2)
print(resp.status)
await session.close()
async def main():
for i in range(2):
tasks = asyncio.create_task(get_https())
print(f"所有协程任务开始执行前的时间:{time.strftime('%X')}")
await tasks
print(f"所有协程任务最后执行前的时间:{time.strftime('%X')}")
asyncio.run(main())
以上就是“Python教程—Python中如何使用async方式实现异步并发?”的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。
扫码二维码 获取免费视频学习资料
- 本文固定链接: http://phpxs.com/post/11628/
- 转载请注明:转载必须在正文中标注并保留原文链接
- 扫码: 扫上方二维码获取免费视频资料
查 看2022高级编程视频教程免费获取