python异步async await用法,python异步async
介绍了目录异步、事件循环过程、线程、协同函数和协同对象等待任务对象异步的概念。未来对象异步迭代器异步上下文管理器
异步的概念与异步的概念相反。同步意味着一个程序只有在另一个程序被执行后才会执行它。
例如,对于单个流程,常见的函数调用是同步执行。只有当被调用的函数完成并返回时,
将继续执行主音调函数中的剩余代码。
虽然在异步中通过await等待异步函数执行也是流程,但是如果一个流程有多个任务,
当它在被调用的异步函数中被阻塞时,它将执行其他任务。
python中的语法是
Async用于将函数声明为异步的。
Await用来声明等待异步函数,后面跟着await执行后返回。
一开始有一个错误的理解:假设有一个伪代码await func_a,当执行到伪代码await func_a时,生成一个类似线程的东西来执行func_a函数。
在不影响当前await func_a代码后的代码运行的情况下,即立即执行下面的语句。
但不是这样的。因为await,所以需要等待func_a结束后再继续执行Awaitfunc _ a后面的代码。
还有一个错误的想法:都是异步的,为什么还要等结果?
回答:假设func_a函数处理后会返回一个结果。如果此时不阻塞await func_a行,将继续向下执行。
然后,如果下一行代码需要使用func_a函数返回的结果,那么就该用这个结果作为None了。
例如,看看代码
进口异步
异步定义函数():
等待睡眠(2)
打印(1)
异步定义函数b():
await func_a()
打印(2)
Asyncio.run(func_b())目前只有一个任务,执行的是func_b(),而func_b在等待func_a,所以在func _ a休眠两秒后。
1,然后返回func_b打印2。
这是因为目前只有一个任务,await是用来等待异步函数完成返回后再继续执行下面的代码。
如果有其他任务,其他任务直到func _ a休眠才会执行。
一个事件可以理解为一个无限循环,检测并执行一些代码。
伪代码
任务列表=[任务1,任务2,任务3。]
虽然正确:
可执行任务列表,已完成任务列表=检查任务列表中的所有任务,并返回可执行和已完成的任务。
#请注意,任务列表中可能有被阻止的任务,此查询将不会被返回。
对于可执行任务列表中的就绪任务:
执行准备好的任务。
对于已完成任务列表中的已完成任务:
从任务列表中删除已完成的任务。
如果任务列表中的所有任务都已完成,并且任务列表为空,则循环终止。
代码:
进口异步
#生成事件循环
loop=asyncio.get_event_loop()
#将任务放在任务列表中
循环运行直到完成(任务)
进程、线程和协同进程是指程序的运行进程,包括程序、代码和进程控制块(PCB)。它们是系统资源分配的独立单元,也是处理器分配和调度的基本单元。
后来为了让操作系统更好的处理并发,引入了线程。此时,线程被视为处理、分派和调度的基本单位。一个进程中的多个线程共享该进程的资源,因此切换上下文会更快。
进程和线程是操作系统级的概念。
为了进一步提高上下文切换的效率,协同处理由程序员自己通过代码来调度。
一个进程可以对应多个线程,一个线程可以对应多个协程。
然而,在某一时刻,一个进程中只能运行一个线程。类似地,在某一时刻,一个线程的协程中只能运行一个协程。
协程的概念是,如果一个线程遇到IO或其他等待操作,该线程将使用其空闲时间来处理其他任务。但前提是这个线程有多个协同任务。
进口异步
异步定义函数1():
打印(1)
AwaasyncIO.sleep (2) #遇到IO自动切换
打印(2)
异步定义函数2():
打印(3)
等待睡眠(2)
打印(4)
def main():
任务=[
func1(),
函数2()
]
#下面两行可以理解为创建两个任务
loop=asyncio.get_event_loop()
loop . run _ until _ complete(asyncio . wait(tasks))
if __name__==__main__ :
main()结果的打印顺序是1324。
先了解主进程运行一个协调的func1,打印1,然后遇到sleep,再挂起func1执行另一个任务func2打印3。
当func1睡眠结束后,无论func2的协同过程执行到哪里,都会返回到func1向下执行,打印2后协同过程结束。
然后执行func2的print 4。
协同功能和协同对象协同功能:定义功能时使用异步定义。
协同处理对象:执行协同处理功能的对象。
异步定义函数():
及格
Result=func()结果成为协程对象,此时不会执行func的内部代码。如果要运行协程函数的内部代码,必须把协程对象交给事件循环处理。
进口异步
异步定义函数():
打印(1)
result=func()
#生成事件循环
loop=asyncio.get_event_loop()
#将任务放在任务列表中
Loop.run _ until _ complete(结果)Python 3.7以后使用asynic.run(任务)
进口异步
异步定义函数():
打印(1)
result=func()
Asyncio.run (task)运行包括生成事件的循环列表。
Awaitawait可以等待对象(协同对象、未来对象、任务对象)。
进口异步
异步定义其他():
打印(“开始”)
response=wait asyncio . sleep(2)
打印(“结束”)
return 返回值
异步定义函数():
打印(“执行协同功能的内部代码”)
#当IO操作挂起当前进程(任务)时,等待IO操作完成后再继续执行,
#当当前进程挂起时,事件循环可以执行其他进程(任务)。
响应=等待他人()
打印( IO请求结束于:,响应)
asyncio.run(func())
运行结果是
执行协同功能的内部代码。
开始
目标
IO请求结束,结果是:return-valueawait是等待对象的值得到结果后再继续向下。
Object TaskTask对象用于在事件循环中添加多个任务。
用于任务协同的并发调度,通过asyncio.create_task(协同对象)
以这种方式创建一个任务对象,这样协程就可以加入事件循环,等待被调用执行。
除了asyncio.create_task(),还可以使用低级的loop.create_task()。
或者guarantee _ future()函数。
不寻常的写作方式。
进口异步
异步定义函数():
打印(1)
等待睡眠(2)
打印(2)
return 返回值
异步定义main():
打印(“主开始”)
#创建一个任务对象,将当前执行func函数的任务添加到事件循环中。
task1=asyncio.create_task(func())
task2=asyncio.create_task(func())
ret1=等待任务1
ret2=等待任务2
打印(“主要结束”)
打印(返回1,返回2)
asyncio.run(main())
运行结果
主启动
一个
一个
2
2
主要端
返回值返回值通常是。
进口异步
异步定义函数():
打印(1)
等待睡眠(2)
打印(2)
return 返回值
异步定义main():
打印(“主开始”)
#创建一个任务对象,将当前执行func函数的任务添加到事件循环中。
task_list=[
asyncio.create_task(func(),name=t1 ),
asyncio.create_task(func(),name=t2 )
]
#等待列表中的任务完成
done,pending=await asyncio . wait(task _ list)
# asyncio.wait返回二进制组
打印(“主要结束”)
打印(完成)
Asysio.run (main ()) #这一步创建事件循环。
运行结果
主启动
一个
一个
2
2
主要端
{ Task finished name= t1 coro=func()done,定义在F:\ py charm _ project \ main . py:3 result= return-value ,Task finished name= T2 coro=func()done,定义在F:\ py charm _ project \ main . py:3 result= return-value }也可以这样写。
进口异步
异步定义函数():
打印(1)
等待睡眠(2)
打印(2)
return 返回值
task_list=[
func(),
函数()
]
完成,待定=asyn CIO。运行(asyn CIO。等待(任务列表))
打印(完成)
阿辛西奥。将来的对象工作继承自未来,任务对象内部等待结果的处理基于将来的对象
示例一
异步定义main():
# 获取创建的事件循环
loop=asyncio.get_running_loop()
# 创建一个任务(未来对象),什么都不干
fut=loop.create_future()
# 等待将来的对象,没有结果会一直等下去
等待未来
asyncio.run(main())示例2
进口异步
异步定义set_after(fut):
等待睡眠(2)
fut.set_result(555 )
异步定义main():
# 获取创建的事件循环
loop=asyncio.get_running_loop()
# 创建一个任务(未来对象),什么都不干
fut=loop.create_future()
# 创建一个任务(任务对象),绑定set_after函数,函数内部2s后,会给砰赋值
# 即手动设置将来的任务最终结果
等待循环。create _ task(set _ after(fut))
# 等待将来的对象
数据=等待未来
打印(数据)
阿辛西奥。并发运行(main())。期货。将来的对象(扩展)
使用线程池、进程池实现异步操作时用到的对象
导入时间
从并行未来导入期货
从并行未来导入线程池执行器
从并行未来导入进程池执行器
定义函数(值):
时间。睡眠(1)
打印(值)
返回123
# 创建线程池
pool=ThreadPoolExecutor(max _ workers=5)
# 创建进程池
# pool=ProcessPoolExecutor(max _ workers=5)
对于范围(10)内的我:
fut=pool.submit(func,I)
#打印(未来)
从输出结果可以看到执行结果无序案例:asyncio不支持异步模块
进口异步
导入请求
异步定义下载图像(网址):
打印("开始下载:",网址)
loop=asyncio.get_event_loop()
请求数量模块不支持异步操作,使用线程池配合实现
future=loop.run_in_executor(无、requests.get、url)
回应=等待未来
打印("下载完成")
file_name=url.rsplit(-)[-1]
用打开(文件名,模式=wb )作为fp:
fp.write响应。内容)
if __name__==__main__ :
url_list=[
url1 , url2 , url3
]
任务=[url _ list中统一资源定位器的下载图像(网址)]
loop=asyncio.get_event_loop()
循环。run _ until _ complete(asyncio。等待(任务))
异步迭代器异步迭代器:实现了__aiter__()和__anext__()方法的对象(这两个方法自动执行),必须返回一个值得称赞的对象。异步_for支持处理异步迭代器的__anext__()方法返回的可等待对象,直到引发一个停止沉淀异常
异步可迭代对象:可在异步_for语句中被使用的对象,必须通过它的__aiter__()方法返回一个异步迭代器(异步迭代器)
进口异步
类读取器(对象):
# 自定义异步迭代器,同时也是异步可迭代对象
def __init__(self):
self.count=0
异步定义读取线(自身):
self.count=1
如果self.count==20:
不返回
返回自我计数
def __aiter__(self):
回归自我
异步定义__anext__(self):
val=await self.readline()
如果val==无:
提高停止沉淀
返回值
异步定义函数():
obj=Reader()
对象中项目的异步:
打印(项目)
asyncio.run(func())
异步上下文管理器通过定义_ _ aenter _ _()和__aexit__()方法来对异步_与语句中的环境进行控制,这两个方法自动执行。
进口异步
类AsyncContextManager:
def __init__(self):
自我连接=无
异步定义做某事(自己):
# 异步操作数据库
返回555
异步定义__ a输入_ _(自身):
# 异步连接数据库
自我。conn=wait asyncio。睡眠(1)
回归自我
async def __aexit__(self,exc_type,exc_val,exc_tb):
# 异步关闭数据库
等待睡眠(1)
异步定义函数():
async with AsyncContextManager()as f:
result=await f.do_something()
打印(结果)
asyncio.run(func())
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。