找回密码
 立即注册
首页 业界区 业界 Python异步完全指南

Python异步完全指南

兜蛇 3 天前
Python中并行处理多个任务主要是靠:

  • thread 线程
  • process 进程
  • asyncio 非同步
process

将一个py 脚本放入到内存中,程序就变成了 一个process
process 是程序运行的实例,process 有自己的内存,通信;不同的process之间彼此独立
process 通常分为二种

  • I/O密集型,cpu使用率较低,大量时间在等待网络,用户输入输出
  • CPU 密集型,cpu使用率较高,在大量计算,数据分析,视频编码等
Thread 线程

线程是Process的最小单位,每个Process 至少有一个线程(主线程);线程在同一个process内共享资源,一个线程操作不当,会导致整个process 崩溃。
CPU 执行process / thread的机制

CPU 一次只能执行一个任务,为了处理多个任务,抢占式切换任务。
抢占式切换:process保留当前状态,开辟新的内存空间,增加消耗,在同一个process里,thread 共享空间,所以开销更小。
对于多核CPU ,每个核心都能处理不同的进程。节省了大量的切换开销。
PYTHON GIL锁机制

在同一个process内,GIL是一种锁,允许任何时候只有一个线程控制 Python 解释器。在I/O 等待场景,会释放GIT锁。
GIL 的存在是为了解决竞态问题,防止多个线程彼此大家。
asyncio  异步

asyncio 使用单一线程来处理多个任务,避免了大量上下文切换带来的开销


  • Coroutines 把普通函数定义为协程函数 代表该函数可以暂停/恢复
  • Event loop 事件循环,负责管理执行Coroutines
  • Tasks 协程具体的对象 通过asyncio.create_task()调度
  • await  暂停协程的执行
协程创建之后,不会自动调用。asyncio.run()来运行
适合 需要大量等待的小任务场景
asyncio.create_task()

让函数立即进入队列(不是立即执行,等待其他函数交出控制权)create_task() 解除等待关系,把协程交给事件循环管理;只要存在 await 的让出点,多个任务就可以交叉推进
  1. await a()
  2. await b()
  3. # 交叉
  4. ta = create_task(a())
  5. tb = create_task(b())
  6. await ta
  7. await tb
复制代码
asyncio.to_thread

asyncio.to_thread 让同步阻塞代码在另一个线程运行,从而保证事件循环线程不被阻塞。
  1. async def main():
  2.     print("start")
  3.     asyncio.create_task(
  4.         asyncio.to_thread(fetch_data)
  5.     )
  6.     print("end")
复制代码
写法函数何时执行当前协程是否继续await to_thread()立即(在线程)否(等结果)create_task(to_thread())立即(在线程)是检测判断

你在 async 函数里,要调用一个函数 F

├─ F 是 async 协程函数?
│   │
│   ├─ 是
│   │   │
│   │   ├─ 需要等 F 的结果?
│   │   │   ├─ 是 → await F()
│   │   │   └─ 否 → create_task(F())
│   │   │
│   │   └─(结束)
│   │
│   └─ 否(F 是同步阻塞函数)
│       │
│       ├─ 需要等 F 的结果?
│       │   ├─ 是 → await asyncio.to_thread(F)
│       │   └─ 否 → create_task(asyncio.to_thread(F))
│       │
│       └─(结束)

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册