基础语法糖
| 语法糖 | 功能 | 对应底层机制 |
|---|---|---|
async def | 定义协程函数 | 创建 Coroutine 对象 |
await | 挂起并等待协程完成 | 调用 __await__() 方法 |
async for | 异步迭代 | 使用 __aiter__() 和 __anext__() |
async with | 异步上下文管理 | 使用 __aenter__() 和 __aexit__() |
async def—— 协程函数定义
# 示例
import asyncio
async def hello():
await asyncio.sleep(1)
return "Hello"
# 调用返回协程对象,不立即执行
coro = hello()
print(type(coro)) # <class 'coroutine'>
# 需要 await 或 asyncio.run() 来执行
result = asyncio.run(hello())
# 使用语法糖
async def fetch_data():
return await some_async_operation()
# 等价于(底层实现)
def fetch_data():
async def _coro():
return await some_async_operation()
return _coro()
作用:
-
将普通函数转换为协程函数
-
调用时返回
Coroutine对象,而非直接执行 -
允许在函数内部使用
await
await—— 协程等待
# 示例
async def main():
# await 语法糖:等待两个任务完成
task1 = asyncio.create_task(fetch_user())
task2 = asyncio.create_task(fetch_posts())
user = await task1 # 语法糖:等待任务1
posts = await task2 # 语法糖:等待任务2
return user, posts
# 使用语法糖
result = await coroutine_obj
# 等价于(简化版底层)
result = yield from coroutine_obj.__await__()
# await 的对象必须是 awaitable,如:
# 协程对象 (coroutine)
# 任务 (Task)
# 具有 __await__() 方法的对象
作用:
-
挂起当前协程,让出控制权给事件循环
-
等待目标协程完成后恢复执行
-
只能在
async def函数中使用
async for—— 异步迭代器
# 示例1_异步计数器
class AsyncCounter:
def __init__(self, max_count):
self.max_count = max_count
self.current = 0
def __aiter__(self):
return self # 返回自身作为迭代器
async def __anext__(self):
if self.current >= self.max_count:
raise StopAsyncIteration # 迭代结束信号
# 模拟异步操作(如网络延迟)
await asyncio.sleep(0.1)
value = self.current
self.current += 1
return value
# 使用
async def main():
async for num in AsyncCounter(3):
print(f"Count: {num}")
# 输出:
# Count: 0
# Count: 1
# Count: 2
# 示例2_异步数据库查询
class AsyncDatabaseCursor:
def __init__(self, query):
self.query = query
self.index = 0
def __aiter__(self):
return self
async def __anext__(self):
if self.index >= 3: # 模拟3条记录
raise StopAsyncIteration
# 模拟异步数据库查询
await asyncio.sleep(0.1)
result = f"Record {self.index}"
self.index += 1
return result
async def main():
# async for 语法糖
async for record in AsyncDatabaseCursor("SELECT * FROM users"):
print(record)
# 使用语法糖
async for item in async_iterable:
process(item)
# 等价于(底层展开)
iter_obj = async_iterable.__aiter__()
while True:
try:
item = await iter_obj.__anext__()
process(item)
except StopAsyncIteration:
break
作用:
-
在每次迭代时自动
await下一个元素 -
处理可能涉及
I/O的迭代操作(如数据库游标、网络流)
async with—— 异步上下文管理器
# 示例
class AsyncHTTPClient:
def __init__(self, base_url):
self.base_url = base_url
self.session = None
async def __aenter__(self):
print(f"Creating session for {self.base_url}")
# 模拟异步创建会话
await asyncio.sleep(0.1)
self.session = f"Session-{id(self)}"
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
print(f"Closing session {self.session}")
# 模拟异步关闭会话
await asyncio.sleep(0.1)
self.session = None
# 如果有异常,可以选择处理或传播
if exc_type is not None:
print(f"Exception occurred: {exc_val}")
# 返回 None 或 False 会传播异常
return False
async def get(self, path):
if not self.session:
raise RuntimeError("Session not active")
url = f"{self.base_url}{path}"
print(f"GET {url} using {self.session}")
await asyncio.sleep(0.2) # 模拟网络请求
return f"Response from {url}"
# 使用
async def fetch_data():
async with AsyncHTTPClient("https://api.example.com") as client:
response = await client.get("/users")
print(response)
# 使用语法糖
async with resource as obj:
do_something(obj)
# 等价于(底层展开)
manager = (resource)
aexit = type(manager).__aexit__
aenter_result = type(manager).__aenter__(manager)
try:
obj = aenter_result
do_something(obj)
except Exception as exc:
if not await aexit(manager, type(exc), exc, exc.__traceback__):
raise
else:
await aexit(manager, None, None, None)
作用:
-
异步获取和释放资源
-
常用于需要异步初始化/清理的场景(如网络连接、文件操作)
Python并发编程的核心组成部分
1. 主循环
作用:负责任务调度、IO 事件监听、状态管理
# 主循环
主循环(while ture):
检查所有任务列表中的所有任务 -> 获取可执行的任务列表 + 已完成的任务列表
遍历就绪任务列表:
执行已就绪的任务
遍历已完成的任务列表:
在任务列表中移除已完成的任务
检查任务列表:
如果任务列表中的任务都已完成,则终止循环
功能:
-
获取所有可执行的任务和已经完成的任务
-
执行已经就绪的任务
-
移除已经完成的任务
-
检查任务列表中的任务是否全部完成
注意点:
-
主循环(事件循环)在单线程中运行,所有任务都在这个线程内切换执行。
-
仅当任务遇到
await(表示需要等待IO)时才会切换,纯计算任务不会触发切换。
2. 协程
协程是异步任务的基本单元,是一种用户态的上下文切换技术,其实就是通过一个线程实现代码块相互切换执行,本质是可暂停 / 恢复的函数。
- 调用协程不会立即执行,而是返回一个协程对象。
- 必须通过事件循环调度(如
await、create_task)才能执行。
#示例
import asyncio
async def my_coroutine_1():
print("协程1开始")
await asyncio.sleep(2)
print("协程1结束")
return "结果1"
async def my_coroutine_2():
print("协程2开始")
await asyncio.sleep(1)
print("协程2结束")
return "结果2"
async def main():
result1 = await task1
result2 = await task2
asyncio.run(main())
协程的生命周期:
创建:coro = my_coroutine() → 未执行状态。
运行:await coro 或 create_task(coro) → 进入事件循环。
暂停: 执行到 await 语句 → 等待 IO 时挂起。
恢复:IO 完成 → 从暂停点继续执行。
完成: 执行到函数末尾 → 返回结果或抛出异常。
3. 任务
任务是协程的包装器,由事件循环直接调度,用于实现并发。任务会将协程注册到事件循环,并跟踪其状态(运行中 / 已完成 / 已取消)。
# 示例1
import asyncio
async def my_coroutine_1():
print("协程1开始")
await asyncio.sleep(2)
print("协程1结束")
return "结果1"
async def my_coroutine_2():
print("协程2开始")
await asyncio.sleep(1)
print("协程2结束")
return "结果2"
async def main():
# 同时创建并启动两个任务(并发)
task1 = asyncio.create_task(my_coroutine_1()) # 立即调度执行
task2 = asyncio.create_task(my_coroutine_2()) # 立即调度执行
print("两个协程已启动,正在并发运行...")
# 等待它们完成(顺序 await 不影响执行顺序)
result1 = await task1
result2 = await task2
print("最终结果:", result1, result2)
asyncio.run(main())
# 示例2
async def task_func(name, delay):
print(f"任务 name={name}, delay={delay} === 111")
await asyncio.sleep(delay)
print(f"任务 name={name}, delay={delay} === 222")
return f"任务 {name} 完成"
async def main():
# 创建任务(立即加入事件循环,开始调度)
task_list = [
asyncio.create_task(task_func("A", 1), name="task_A"),
asyncio.create_task(task_func("B", 2), name="task_B"),
]
done, pending = await asyncio.wait(task_list, timeout=None)
# 等待任务完成并获取结果
print(done)
asyncio.run(main())
任务相关语法
-
task.done():判断任务是否完成。 -
task.result():获取任务返回值(任务未完成时调用会报错)。 -
task.cancel():取消任务(触发CancelledError)。 -
task.add_done_callback(func):注册回调函数(任务完成后执行)。
# 示例1_task.done()+task.result()
import asyncio
async def my_coroutine_1():
print("协程1开始")
await asyncio.sleep(2)
print("协程1结束")
return "结果1"
async def my_coroutine_2():
print("协程2开始")
await asyncio.sleep(1)
print("协程2结束")
return "结果2"
async def main():
# 同时创建并启动两个任务(并发)
task1 = asyncio.create_task(my_coroutine_1()) # 立即调度执行
task2 = asyncio.create_task(my_coroutine_2()) # 立即调度执行
print("两个协程已启动,正在并发运行...")
while(1):
print("任务1:",task1.done())
print("任务2:",task2.done())
await asyncio.sleep(0.5)
if task1.done() == True and task1.done() == True:
break;
# 等待它们完成(顺序 await 不影响执行顺序)
result1 = await task1
result2 = await task2
print(task1.result(),task2.result())
asyncio.run(main())
# 示例2_task.cancel()
import asyncio
async def cancellable_task():
try:
print("可取消任务开始")
await asyncio.sleep(3) # 这里会被中断
print("可取消任务结束")
return "正常完成"
except asyncio.CancelledError:
print("任务被取消!")
raise # 重新抛出以确保任务状态为 cancelled
async def cancel_demo():
task = asyncio.create_task(cancellable_task())
# 1秒后取消任务
await asyncio.sleep(1)
task.cancel()
try:
result = await task
except asyncio.CancelledError:
print("主函数捕获到取消异常")
print(f"任务完成状态: {task.done()}") # True
print(f"任务被取消: {task.cancelled()}") # True
asyncio.run(cancel_demo())
# 示例3_task.add_done_callback(func)
import asyncio
async def my_coroutine_1():
print("协程1开始")
await asyncio.sleep(2)
print("协程1结束")
return "结果1"
async def my_coroutine_2():
print("协程2开始")
await asyncio.sleep(3)
print("协程2结束")
return "结果2"
def check_task(future):
# 注意:这里需要访问 task1,所以要用全局变量或闭包
global task1_global
if task1_global.done():
print("task1 已经完成")
else:
print("task1 还未完成")
async def main():
global task1_global
# 创建任务
task1 = asyncio.create_task(my_coroutine_1())
task2 = asyncio.create_task(my_coroutine_2())
# 保存 task1 的引用给回调函数使用
task1_global = task1
# 立即注册回调(在任务可能完成之前!)
task2.add_done_callback(check_task)
# 等待所有任务完成
result1 = await task1
result2 = await task2 # 这行其实可以省略,因为 task2 已经完成了
print(f"最终结果: {result1}, {result2}")
asyncio.run(main())
4. Future 对象
Task 与 Future 的关系:
-
Task 继承自 Future,是 “可执行的 Future”(绑定了协程)。
-
Future 更底层,通常用于手动管理异步操作结果(如包装回调式 API)
365

被折叠的 条评论
为什么被折叠?



