Python协程入门必读:从生成器基础到async/await实战
发表于|更新于
|总字数:637|阅读时长:2分钟|浏览量:
协程(Coroutine)是Python异步编程的核心,但许多开发者对其底层原理和演进过程一知半解。本文将通过生成器进化史的视角,带您从基础到实战完整掌握协程开发,最后还会揭秘async/await背后的魔法。
一、理解生成器(Generator)
生成器是一种惰性计算的迭代器,用 yield 关键字定义。它不会一次性生成所有数据,而是按需生成。
1.1 生成器的本质
def simple_gen(): print("start") yield 1 print("continue") yield 2 gen=simple_gen() print('=====>test') print(next(gen)) print('=====>test') print(next(gen))
|
生成器通过yield实现执行暂停,每次调用next()恢复执行直到遇到下一个yield。
1.2 生成器的双向通信
def interactive_gen(): response = yield "What's your name?" yield f"Hello, {response}!"
gen = interactive_gen() print(next(gen)) print(gen.send("Alice"))
|
通过.send()方法实现双向数据传递,建立协程的雏形
二、生成器进化成协程
2.1 yield from语法
def sub_gen(): yield 2 yield 3
def main_gen(): yield 1 yield from sub_gen() yield 4
list(main_gen())
|
yield from实现生成器委托,为协程的任务嵌套奠定基础
2.2 异常处理机制
def error_gen(): try: yield "normal" except ValueError: yield "error"
gen = error_gen() print(next(gen)) print(gen.throw(ValueError))
|
.throw()和.close()方法让生成器具备完整的异常处理能力
三、现代协程体系:async/await
3.1 事件循环原理
想象一个高效的快递调度员:
import asyncio async def delivery(name, time): print(f"{name}快递开始送出") await asyncio.sleep(time) print(f"{name}快递已送达")
async def main(): tasks = [ delivery("A", 2), delivery("B", 1), delivery("C", 3) ] await asyncio.gather(*tasks)
asyncio.run(main())
|
输出顺序:
A快递开始送出
B快递开始送出
C快递开始送出
B快递已送达
A快递已送达
C快递已送达
关键点:
并发执行:A 和 B 几乎同时开始。
非阻塞:await asyncio.sleep 不会阻塞线程,而是让出控制权给事件循环。
四、实战:异步HTTP客户端
4.1 使用aiohttp
import aiohttp
async def fetch_url(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.text()
async def batch_fetch(): urls = [...] tasks = [fetch_url(url) for url in urls] return await asyncio.gather(*tasks)
|
对比同步版本速度提升20倍以上