如何在Python中使用async/await?

如何在Python中使用async/await?
最新回答
暧昧不是爱情是毒药

2021-10-23 02:23:24

在Python中使用async/await进行异步编程的核心步骤如下:

1. 定义异步函数

使用async def声明异步函数,函数内部可包含await表达式。异步函数本质是协程(coroutine),需通过事件循环驱动执行。

async def say_after(delay, what): await asyncio.sleep(delay) # 模拟I/O操作 print(what)2. 使用await等待异步操作
  • await用于暂停协程执行,直到异步操作完成(如I/O请求、定时器等)。
  • 必须在异步函数内部使用await,否则会触发语法错误。
async def main(): await say_after(1, 'hello') # 等待1秒后打印 await say_after(2, 'world') # 等待2秒后打印3. 运行异步程序

通过asyncio.run()启动事件循环并执行主协程:

asyncio.run(main())
  • 输出结果:hello(1秒后)→ world(再2秒后)。
4. 并发执行多个协程

使用asyncio.gather()或asyncio.create_task()实现并发:

async def main(): # 方法1:asyncio.gather() 并发执行 await asyncio.gather( say_after(1, 'hello'), say_after(2, 'world') ) # 方法2:asyncio.create_task() 显式创建任务 task1 = asyncio.create_task(say_after(1, 'hello')) task2 = asyncio.create_task(say_after(2, 'world')) await task1 await task2
  • 输出结果:hello和world几乎同时开始,但world因延迟更长而最后完成。
5. 实际应用示例:异步HTTP请求

结合aiohttp库实现并发HTTP请求:

import aiohttpimport asyncioasync def fetch(session, url): async with session.get(url) as response: return await response.text()async def main(): async with aiohttp.ClientSession() as session: urls = [ '
https://example.com/page1'
, '
https://example.com/page2'
] # 并发请求所有URL results = await asyncio.gather(*[fetch(session, url) for url in urls]) print(results)asyncio.run(main())注意事项
  • 错误处理:使用try/except捕获协程内异常,或通过asyncio.gather()的return_exceptions参数统一处理。try: await some_async_function()except Exception as e: print(f"Error: {e}")
  • 适用场景:优先用于I/O密集型任务(如网络请求、文件读写),CPU密集型任务建议使用多线程/多进程。
  • 避免阻塞操作:在协程内禁止使用同步I/O操作(如time.sleep()),应替换为异步版本(如asyncio.sleep())。
  • 代码可读性:过度嵌套await可能导致逻辑混乱,建议拆分复杂协程。
常见问题
  • 未使用await的后果:协程不会执行,仅返回协程对象。async def main(): say_after(1, 'hello') # 无await,不会打印asyncio.run(main()) # 无输出
  • 混合同步与异步代码:需通过loop.run_in_executor()将同步代码放入线程池执行。

通过合理使用async/await,可显著提升I/O密集型程序的性能,但需注意设计模式和错误处理的复杂性。