2. 异步编程
事件循环
事件循环(Event Loop)是异步编程的核心机制,可以理解为一个死循环,去检测并执行某些代码。
事件循环的工作原理可以用以下伪代码来描述:
text
# 伪代码
任务列表 = [ 任务1, 任务2, 任务3,... ]
while True:
可执行的任务列表, 已完成的任务列表 = 去任务列表中检查所有的任务,将'可执行'和'已完成'的任务返回
for 就绪任务 in 可执行的任务列表:
执行已就绪的任务
for 已完成的任务 in 已完成的任务列表:
在任务列表中移除 已完成的任务
如果 任务列表 中的任务都已完成,则终止循环python
import asyncio
# 去生成一个事件循环
loop = asyncio.get_event_loop()
# 将任务放进任务列表,让事件循环去检测任务状态
loop.run_until_complete()快速上手
协程函数,定义函数时候 async def,调用函数时候 await。 协程对象,执行 协程函数() 返回的对象。
python
# 定义协程函数
async def func():
pass
# 获取协程对象
result = func()注意:执行协程函数创建协程对象时,并不会立即执行函数体内的代码,只有在事件循环中运行该协程对象时,函数体内的代码才会被执行。
python
import asyncio
async def func():
print("Start func")
result = func()
# loop = asyncio.get_event_loop()
# loop.run_until_complete(result)
asyncio.run(result) # Python 3.7 及以上版本推荐使用, 代替上面两行代码await
await + 可等待的对象(协程对象、Future、Task 对象 -> IO 等待)
python
import asyncio
async def others():
print(" [others] Start others")
await asyncio.sleep(1) # 遇到IO,会切换去执行其他任务
print(" [others] End others")
return "Result from others"
async def func():
print("[func] Start func")
await asyncio.sleep(2) # 遇到IO,会切换去执行其他任务
print("[func] End func")
return "Result from func"
async def main():
# 创建task对象,将当前执行的函数func()和others()加入事件循环中
task1 = asyncio.create_task(func())
task2 = asyncio.create_task(others())
# 等待两个任务完成
result1 = await task1
result2 = await task2
print(f"\n结果: {result1}, {result2}")
asyncio.run(main())
# 执行顺序:
# 1. [func] Start func -> 遇到 sleep(2),切换到 task2
# 2. [others] Start others -> 遇到 sleep(1),切换
# 3. 1秒后 others 的 sleep 完成 -> [others] End others
# 4. 2秒后 func 的 sleep 完成 -> [func] End func
# 最后输出结果:
# [func] Start func
# [others] Start others
# [others] End others
# [func] End func
# 结果: Result from func, Result from otherstask 对象
Tasks 用于并发调度协程,通过 asyncio.create_task(协程对象) 的方式创建 Task 对象,这样可以让协程加入到事件循环中进行调度执行。
白话:在事件循环中添加多个任务
python
import asyncio
async def func():
print("Start func")
await asyncio.sleep(1)
print("End func")
return "Result from func"
async def main():
print("Creating task...")
task_list = [
asyncio.create_task(func(), name="n1"),
asyncio.create_task(func(), name="n2"),
]
print("Tasks created, waiting for results...")
done, pending = await asyncio.wait(task_list)
print(done)
asyncio.run(main())python
import asyncio
async def func():
print("Start func")
await asyncio.sleep(1)
print("End func")
return "Result from func"
task_list = [
func(),
func(),
]
done, pending = asyncio.run(asyncio.wait(task_list))
print(done)asyncio.Future 对象
task 对象是继承Future对象,task对象内部await结果的处理基于Future对象来实现的。
concurrent.futures.Future 对象
使用线程池、进程池实现异步操作时用到的对象。
异步迭代器
异步上下文管理器
此种对象通过定义 __aenter__ 和 __aexit__ 方法来对 async with 语句中的环境进行控制。
python
import asyncio
class AsyncContextManager:
async def __init__(self):
pass
async def do_something(self):
print("Doing something asynchronously")
async def __aenter__(self):
# 操作之前先打开
print("Entering async context")
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
# 操作之后再关闭
print("Exiting async context")
async def main():
# async with 必须放在协程函数内, manager 是__aenter__返回的对象
async with AsyncContextManager() as manager:
result = await manager.do_something()
print(result)
asyncio.run(main())