[Python3高阶编程] - 异步编程深度学习指南一(补充1):深入理解关键词 async
async是 Python 异步编程的基石关键字,它和await一起构成了现代 Python 异步 I/O 的核心语法。
一、async的核心作用
async关键字用于定义“协程函数”(coroutine function)——一种可以暂停和恢复执行的特殊函数。
类比理解:
- 普通函数:像一条直线,从头跑到尾,中间不能停。
- 协程函数(
async def):像一条有“检查点”的跑道,跑到await处可以暂停,让别人先跑,等轮到自己再继续。
二、async怎么使用?——基本语法
基本形式:
async def function_name(parameters): # 函数体 await some_async_operation() # 可选,但通常会有 return result示例 1:最简单的协程函数
async def greet(name): return f"Hello, {name}!" # 调用它 coro = greet("Alice") print(type(coro)) # <class 'coroutine'> —— 返回一个协程对象,不是结果!⚠️ 注意:调用
greet("Alice")不会立即执行函数体,而是返回一个协程对象(coroutine object)。
三、async defvs 普通def的关键区别
全屏复制
| 特性 | def(普通函数) | async def(协程函数) |
|---|---|---|
| 调用返回值 | 直接返回结果 | 返回协程对象(需await或事件循环执行) |
内部能否用await | ❌ 不能 | ✅ 可以 |
| 执行方式 | 立即执行 | 需由事件循环调度执行 |
| 是否可暂停 | ❌ 不可 | ✅ 在await处可暂停 |
四、如何真正“运行”一个协程函数?
仅仅调用async def函数不会执行它!你需要以下方式之一:
方式 1:在另一个协程中await它(推荐)
async def main(): result = await greet("Bob") # ✅ 真正执行并获取结果 print(result) # Hello, Bob!方式 2:用asyncio.run()启动(顶层入口)
import asyncio # 在脚本顶层 result = asyncio.run(greet("Charlie")) print(result) # Hello, Charlie!方式 3:提交给事件循环(高级)
loop = asyncio.new_event_loop() task = loop.create_task(greet("David")) loop.run_until_complete(task) print(task.result()) # Hello, David!✅最佳实践:
- 应用入口用
asyncio.run(main())- 内部协程互相调用用
await
五、async的常见使用场景
场景 1:异步 I/O 操作(网络、文件、数据库)
import aiohttp async def fetch(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.text()场景 2:并发执行多个任务
async def main(): urls = ["https://a.com", "https://b.com"] tasks = [fetch(url) for url in urls] results = await asyncio.gather(*tasks) # 并发获取场景 3:异步上下文管理器
async def read_file(path): async with aiofiles.open(path, 'r') as f: # 异步文件操作 return await f.read()场景 4:异步生成器(async def+yield)
async def async_range(n): for i in range(n): await asyncio.sleep(0.1) yield i async def main(): async for x in async_range(3): # 异步迭代 print(x)六、重要规则与限制
✅ 规则 1:await只能在async def中使用
def bad(): await something() # ❌ SyntaxError!✅ 规则 2:async def函数必须被正确执行
# 错误:创建了协程但没执行 greet("Eve") # 警告:coroutine 'greet' was never awaited✅ 规则 3:不要在async def中调用阻塞函数
async def bad_io(): time.sleep(2) # ❌ 阻塞整个事件循环! async def good_io(): await asyncio.sleep(2) # ✅ 非阻塞七、async修饰的其他对象(进阶)
除了函数,async还可用于:
1.异步上下文管理器(__aenter__,__aexit__)
class AsyncResource: async def __aenter__(self): print("Acquiring resource") return self async def __aexit__(self, *args): print("Releasing resource") async def main(): async with AsyncResource() as res: # ✅ pass2.异步迭代器(__aiter__,__anext__)
class AsyncCounter: def __init__(self, n): self.n = n self.i = 0 def __aiter__(self): return self async def __anext__(self): if self.i < self.n: await asyncio.sleep(0.1) self.i += 1 return self.i raise StopAsyncIteration async def main(): async for x in AsyncCounter(3): # ✅ print(x)八、常见误区澄清
❌ 误区 1:“加了async就变快了”
✅ 正确:async本身不加速,只有配合异步 I/O和并发才能提升吞吐量。
❌ 误区 2:“async def函数会自动并发执行”
✅ 正确:必须用create_task()或gather()显式并发,否则仍是顺序执行。
❌ 误区 3:“async/await是多线程”
✅ 正确:默认是单线程事件循环,通过协作式多任务实现并发。
九、总结:async的本质
全屏复制
| 问题 | 答案 |
|---|---|
async作用? | 定义可暂停/恢复的协程函数 |
| 如何使用? | async def func(): ... |
| 调用后发生什么? | 返回协程对象,需await或事件循环执行 |
| 必须搭配什么? | 通常搭配await使用 |
| 适用场景? | I/O 密集型任务(网络、文件、DB) |
💡终极口诀:
“async定义暂停点,await触发执行流;
单线程高并发,I/O 等待不再愁。”
掌握async,你就掌握了 Python 异步编程的第一把钥匙!
