Python协程实战:async/await深度解析
引言
在Python开发中,协程是实现异步编程的核心技术。作为一名从Rust转向Python的后端开发者,我深刻体会到协程在并发编程方面的优势。Python 3.5+引入的async/await语法使得协程编程变得更加简洁和直观。
协程核心概念
什么是协程
协程是一种轻量级的并发编程方式,具有以下特点:
- 轻量级:协程比线程更轻量,创建和切换开销小
- 协作式:协程主动让出控制权
- 异步IO:支持异步读写操作
- 代码简洁:使用async/await语法
- 高并发:支持大量并发任务
架构设计
┌─────────────────────────────────────────────────────────────┐
│ 协程架构 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 事件循环 │───▶│ 协程调度 │───▶│ 任务队列 │ │
│ │ (Event Loop)│ │ (Scheduler) │ │ (Task Queue)│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ async/await 语法与协程执行 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
环境搭建与基础配置
基本协程
import asyncio
async def hello():
print("Hello")
await asyncio.sleep(1)
print("World")
asyncio.run(hello())
协程函数
import asyncio
async def fetch_data():
print("Start fetching")
await asyncio.sleep(2)
print("Data fetched")
return {"data": 42}
async def main():
result = await fetch_data()
print(result)
asyncio.run(main())
高级特性实战
并发执行
import asyncio
async def task1():
await asyncio.sleep(2)
return "Task 1 completed"
async def task2():
await asyncio.sleep(1)
return "Task 2 completed"
async def task3():
await asyncio.sleep(3)
return "Task 3 completed"
async def main():
results = await asyncio.gather(task1(), task2(), task3())
print(results)
asyncio.run(main())
任务取消
import asyncio
async def long_running_task():
try:
while True:
print("Running...")
await asyncio.sleep(1)
except asyncio.CancelledError:
print("Task cancelled")
async def main():
task = asyncio.create_task(long_running_task())
await asyncio.sleep(3)
task.cancel()
await task
asyncio.run(main())
超时处理
import asyncio
async def slow_operation():
await asyncio.sleep(5)
return "Done"
async def main():
try:
result = await asyncio.wait_for(slow_operation(), timeout=2)
print(result)
except asyncio.TimeoutError:
print("Timeout")
asyncio.run(main())
实际业务场景
场景一:并发HTTP请求
import asyncio
import aiohttp
async def fetch_url(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
'https://example.com',
'https://google.com',
'https://github.com'
]
async with aiohttp.ClientSession() as session:
tasks = [fetch_url(session, url) for url in urls]
results = await asyncio.gather(*tasks)
for url, content in zip(urls, results):
print(f"{url}: {len(content)} bytes")
asyncio.run(main())
场景二:数据库操作
import asyncio
import asyncpg
async def query_database():
conn = await asyncpg.connect(user='user', password='pass', database='db')
values = await conn.fetch('SELECT * FROM users')
await conn.close()
return values
asyncio.run(query_database())
性能优化
使用任务池
import asyncio
async def process_item(item):
await asyncio.sleep(0.1)
return item * 2
async def main():
items = range(100)
tasks = [process_item(item) for item in items]
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
限制并发数
import asyncio
async def worker(queue):
while True:
item = await queue.get()
await asyncio.sleep(0.1)
print(f"Processed: {item}")
queue.task_done()
async def main():
queue = asyncio.Queue()
for i in range(100):
queue.put_nowait(i)
workers = [asyncio.create_task(worker(queue)) for _ in range(10)]
await queue.join()
for w in workers:
w.cancel()
asyncio.run(main())
总结
协程为Python开发者提供了强大的异步编程能力。通过async/await语法,Python的协程变得非常易用和直观。从Rust开发者的角度来看,Python的协程比Rust的async/await更加成熟和易用。
在实际项目中,建议合理使用协程来提高并发性能,并注意任务调度和错误处理。
338



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



