当前位置: 首页 > news >正文

Python 协程全解析:async/await、asyncio.run、协程 vs 多线程、I/O 密集首选协程

一、什么是协程?

协程(Coroutine)是一种轻量级的用户态线程,它由程序自己控制什么时候挂起、什么时候恢复,不依赖操作系统线程调度。

在 Python 中,协程是通过 async/await 实现的异步编程模型,依赖于事件循环(asyncio)进行调度。


二、async/await 的作用是什么?

  • async def:声明一个异步函数(协程函数),调用它返回一个协程对象。
  • await:在协程中挂起当前执行,等待另一个协程完成后再继续。

✅ 示例代码:

import asyncioasync def say_hello():await asyncio.sleep(1)print("Hello")asyncio.run(say_hello())

三、asyncio.run() 的作用是什么?

✅ 简洁定义:
asyncio.run() 是运行协程程序的推荐入口。

✅ 它做了什么?

  • 创建事件循环
  • 执行协程直到完成
  • 自动关闭事件循环
  • 返回协程的运行结果

✅ 示例:

import asyncioasync def main():await asyncio.sleep(1)return "任务完成"result = asyncio.run(main())
print(result)

四、async 函数必须包含 await 吗?

❌ 答案:不是必须,但通常推荐。

async def hello():print("Hi")  # 没有 await 也合法asyncio.run(hello())

但这样写就失去了异步的意义,等同于普通函数。

五、协程调用协程是否必须 await?

✅ 是的!调用异步函数必须加 await 才会执行,否则只会返回一个协程对象,但不会运行。

❌ 错误示例:

async def inner():print("Inner")async def outer():inner()  # ❌ 没有 await,不会执行!asyncio.run(outer())

✅ 正确写法:

async def inner():print("Inner")async def outer():await inner()  # 👍 正确执行asyncio.run(outer())

六、协程和多线程的区别是什么?

对比项协程(asyncio)多线程(threading)
并发模型协作式抢占式
本质单线程多线程
是否阻塞非阻塞(主动让出)阻塞(由操作系统调度)
适合场景I/O 密集I/O 或部分 CPU 密集
性能消耗低(轻量级,切换开销小)高(线程切换与上下文开销大)
是否需要加锁通常不需要需要(避免数据竞争)

七、I/O 密集任务是否首选协程?

✅ 是的!

协程非常适合处理 I/O 密集场景,比如:

  • 网络请求
  • 数据库访问
  • 文件读写
  • WebSocket 通信

✅ 实例对比:并发请求 5 个网页

1. 同步方式(低效)

import requests
import timeurls = ['https://httpbin.org/delay/1'] * 5start = time.time()
for url in urls:requests.get(url)
print("同步耗时:", time.time() - start)## 2. 异步方式(高效)
```python
import asyncio
import aiohttp
import timeurls = ['https://httpbin.org/delay/1'] * 5async def fetch(session, url):async with session.get(url) as response:return await response.text()async def main():async with aiohttp.ClientSession() as session:tasks = [fetch(session, url) for url in urls]await asyncio.gather(*tasks)start = time.time()
asyncio.run(main())
print("异步耗时:", time.time() - start)

✅ 异步方式可大大缩短总耗时,支持高并发请求。

八、总结:协程的使用建议

场景是否推荐协程
网络请求(爬虫、API)✅ 强烈推荐
数据库访问(async 驱动)✅ 推荐
文件异步读写✅ 推荐
高并发定时任务✅ 推荐
CPU 密集型(图像处理等)❌ 不推荐,建议用多进程

📌 补充:为什么 Jupyter Notebook 中不能直接使用 asyncio.run()

在 Jupyter Notebook(或 IPython)中,事件循环已经自动运行,用于支持 await 表达式的直接运行。因此:

await some_coroutine()
# 在 Notebook 中是合法的,不需要放入 async def 函数中,也不需要 asyncio.run()。

❌ 如果你强行使用 asyncio.run() 会报错:

RuntimeError: asyncio.run() cannot be called from a running event loop

✅ 正确的解决方法(推荐):

方法 1:直接使用 await(Jupyter 专属)

import asyncioasync def say_hello():await asyncio.sleep(1)print("Hello")await say_hello()  # ✅ Jupyter 中可以直接这样写

方法 2:使用 nest_asyncio 兼容运行

import nest_asyncio
import asyncionest_asyncio.apply()  # 允许嵌套事件循环async def say_hello():await asyncio.sleep(1)print("Hello")asyncio.run(say_hello())  # ✅ 现在也能用了

✅ 总结:

环境是否能用 asyncio.run()推荐方式
普通 Python 脚本✅ 可以asyncio.run()
Jupyter Notebook❌ 默认不行直接使用 awaitnest_asyncio
http://www.xdnf.cn/news/955549.html

相关文章:

  • EasyExcel读取csv文件乱码
  • 在 JavaScript中编写 Appium 测试(入门)
  • 【后端】单点登录
  • BI系统帮助企业释放数据价值
  • 技术突破与落地应用:端到端 2.0 时代辅助驾驶TOP10 论文深度拆解系列【第二篇(排名不分先后)】
  • Zabbix 高可用架构部署方案(2最新版)
  • DAY 45 超大力王爱学Python
  • JAVA实战开源项目:经方药食两用服务平台 (Vue+SpringBoot) 附源码
  • day030-Shell自动化编程-函数
  • Ubuntu Linux环境查看服务器资源,查询CPU,内存,环境变量等命令
  • 标注工具核心代码解析——load_image【canvas.py]
  • NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
  • 深度解析:DDoS攻击及其防御策略
  • 【深度解析】以太坊中的挖矿难度调整机制:从动态调节到“冰河时代”的倒计时
  • FOPLP vs CoWoS
  • 二、ROS2完成Docker容器和宿主机通信,使用ros2 topic list看到,但是无法echo
  • 驭码 CodeRider 2.0 产品体验:智能研发的革新之旅
  • OceanBase 桌面版
  • 从零开始了解数据采集(二十八)——制造业数字孪生
  • Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
  • 基于FPGA的PID算法学习———实现P比例控制算法
  • 协同过滤算法进行电影推荐
  • java教程笔记(十三)-synchronized和ReentrantLock
  • Hilt vs Dagger2:Android 依赖注入框架对比
  • 2025年css+html面试题
  • PH热榜 | 2025-06-07
  • 有限自动机到正规文法转换器v1.0
  • 土建施工员考试:建筑施工技术重点知识有哪些?
  • Java中方法调用参数传递机制的理解和示例验证
  • NFT模式:数字资产确权与链游经济系统构建