展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Python multiprocessing模块中进程间通信的实现方式有哪些?

Python multiprocessing模块中进程间通信的实现方式有哪些?

1、为什么要掌握进程间通信python的多线程代码效率由于受制于GIL,不能利用多核CPU来加速,而多进程方式可以绕过GIL,发挥多CPU加速的优势,能够明显提高程序的性能但进程间通信却是不得不考虑的问题。进程不同于线程,进程有自己的独立内存空间,不能使用全局变量在进程间传递数据。实际项目需求中,常常存在密集计算、或实时性任务,进程之间有时需要传递大量数据,如图片、大对象等,传递数据如果通过文件序列化、或网络接口来进行,难以满足实时性要求,采用redis,或者kaffka,rabbitMQ之第3方消息队列

本文目录

      1、为什么要掌握进程间通信

      python的多线程代码效率由于受制于GIL,不能利用多核CPU来加速,而多进程方式可以绕过GIL, 发挥多CPU加速的优势,能够明显提高程序的性能

      但进程间通信却是不得不考虑的问题。 进程不同于线程,进程有自己的独立内存空间,不能使用全局变量在进程间传递数据。

      Python multiprocessing模块中进程间通信的实现方式有哪些?

      实际项目需求中,常常存在密集计算、或实时性任务,进程之间有时需要传递大量数据,如图片、大对象等,传递数据如果通过文件序列化、或网络接口来进行,难以满足实时性要求,采用redis,或者kaffka, rabbitMQ 之第3方消息队列包,又使系统复杂化了。

      Python multiprocessing 模块本身就提供了消息机制、同步机制、共享内存等各种非常高效的进程间通信方式。

      了解并掌握 python 进程间通信的各类方式的使用,以及安全机制,可以帮助大幅提升程序运行性能。

      2、进程间各类通信方式简介

      进程间通信的主要方式总结如下

      Python multiprocessing模块中进程间通信的实现方式有哪些?

      关于进程间通信的内存安全
      内存安全意味着,多进程间可能会因同抢,意外销毁等原因造成共享变量异常。
      Multiprocessing 模块提供的Queue, Pipe, Lock, Event 对象,都已实现了进程间通信安全机制。
      采用共享内存方式通信,需要在代码中自已来跟踪、销毁这些共享内存变量,否则可能会出同抢、未正常销毁等。造成系统异常。 除非开发者很清楚共享内存使用特点,否则不建议直接使用此共享内存,而是通过Manager管理器来使用共享内存。

      内存管理器Manager
      Multiprocessing提供了内存管理器Manager类,可统一解决进程通信的内存安全问题,可以将各种共享数据加入管理器,包括 list, dict, Queue, Lock, Event, Shared Memory 等,由其统一跟踪与销毁。

      3、消息机制通信

      1) 管道 Pipe 通信方式

      类似于1上简单的socket通道,双端均可收发消息。
      Pipe 对象的构建方法:

      parent_conn, child_conn = Pipe(duplex=True/False)

      参数说明

      • duplex=True, 管道为双向通信

      • duplex=False, 管道为单向通信,只有child_conn可以发消息,parent_conn只能接收。

      示例代码:

      from multiprocessing import Process, Pipe
         def myfunction(conn):
            conn.send(['hi!! I am Python'])
            conn.close()
      
      if __name__ == '__main__':
            parent_conn, child_conn = Pipe()
            p = Process(target=myfunction, args=(child_conn,))
            p.start()
        	print (parent_conn.recv() )
      	p.join()

      2) 消息队列Queue 通信方式

      Multiprocessing 的Queue 类,是在python queue 3.0版本上修改的, 可以很容易实现生产者 – 消息者间传递数据,而且Multiprocessing的Queue 模块实现了lock安全机制。

      Python multiprocessing模块中进程间通信的实现方式有哪些?

      Queue模块共提供了3种类型的队列。

      (1) FIFO queue , 先进先出,

      class queue.Queue(maxsize=0)

      (2) LIFO queue, 后进先出, 实际上就是堆栈

      class queue.LifoQueue(maxsize=0)

      (3) 带优先级队列, 优先级最低entry value lowest 先了列

      class queue.PriorityQueue(maxsize=0)

      Multiprocessing.Queue类的主要方法:

      methodDescription
      queue.qsize()返回队列长度
      queue.full()队列满,返回 True, 否则返回False
      queue.empty()队列空,返回 True, 否则返回False
      queue.put(item)将数据写入队列
      queue.get()将数据抛出队列 ,
      queue.put_nowait(item), queue.get_nowait()无等待写入或抛出

      说明:

      • put(), get() 是阻塞方法, 而put_notwait(), get_nowait()是非阻塞方法。

      • Multiprocessing 的Queue类没有提供Task_done, join方法

      Queue模块的其它队列类:
      (1) SimpleQueue
      简洁版的FIFO队列, 适事简单场景使用

      (2) JoinableQueue子类
      Python 3.5 后新增的 Queue的子类,拥有 task_done(), join() 方法

      • task_done()表示,最近读出的1个任务已经完成。

      • join()阻塞队列,直到queue中的所有任务都已完成。

      producer – consumer 场景,使用Queue的示例

      import multiprocessing
      
      def producer(numbers, q):
          for x in numbers:
              if x % 2 == 0:
                  if q.full():
                      print("queue is full")
                      break
                  q.put(x)
                  print(f"put {x} in queue by producer")
          return None
      
      def consumer(q):
          while not q.empty():
              print(f"take data {q.get()} from queue by consumer")
          return None
      
      if __name__ == "__main__":
          # 设置1个queue对象,最大长度为5
          qu = multiprocessing.Queue(maxsize=5,) 
      
          # 创建producer子进程,把queue做为其中1个参数传给它,该进程负责写
          p5 = multiprocessing.Process(
              name="producer-1",
              target=producer,
              args=([random.randint(1, 100) for i in range(0, 10)], qu)
          )
          p5.start()
          p5.join()
          #创建consumer子进程,把queue做为1个参数传给它,该进程中队列中读
          p6 = multiprocessing.Process(
              name="consumer-1",
              target=consumer,
              args=(qu,)
          )
          p6.start()
          p6.join()
      
          print(qu.qsize())

      4、同步机制通信

      (1) 进程间同步锁 – Lock

      Multiprocessing也提供了与threading 类似的同步锁机制,确保某个时刻只有1个子进程可以访问某个资源或执行某项任务, 以避免同抢。

      例如:多个子进程同时访问数据库表时,如果没有同步锁,用户A修改1条数据后,还未提交,此时,用户B也进行了修改,可以预见,用户A提交的将是B个修改的数据。

      添加了同步锁,可以确保同时只有1个子进程能够进行写入数据库与提交操作。

      如下面的示例,同时只有1个进程可以执行打印操作。

      from multiprocessing import Process, Lock
      
      def f(l, i):
          l.acquire()
          try:
              print('hello world', i)
          finally:
              l.release()
      
      if __name__ == '__main__':
          lock = Lock()
      
          for num in range(10):
              Process(target=f, args=(lock, num)).start()

      (2) 子进程间协调机制 – Event

      Event 机制的工作原理:

      1个event 对象实例管理着1个 flag标记, 可以用set()方法将其置为true, 用clear()方法将其置为false, 使用wait()将阻塞当前子进程,直至flag被置为true.
      这样由1个进程通过event flag 就可以控制、协调各子进程运行。

      Event object的使用方法:
      1)主函数: 创建1个event 对象, flag = multiprocessing.Event() , 做为参数传给各子进程
      2) 子进程A: 不受event影响,通过event 控制其它进程的运行
      o 先clear(),将event 置为False, 占用运行权.
      o 完成工作后,用set()把flag置为True。
      3) 子进程B, C: 受event 影响
      o 设置 wait() 状态,暂停运行
      o 直到flag重新变为True,恢复运行

      主要方法:

      • set(), clear()设置 True/False,

      • wait() 使进程等待,直到flag被改为true.

      • is_set(), Return True if and only if the internal flag is true.

      验证进程间通信 – Event

      import multiprocessing
      import time
      import random
      
      def joo_a(q, ev):
          print("subprocess joo_a start")
          if not ev.is_set():
              ev.wait()
          q.put(random.randint(1, 100))
          print("subprocess joo_a ended")
      
      def joo_b(q, ev):
          print("subprocess joo_b start")
          ev.clear()
          time.sleep(2)
          q.put(random.randint(200, 300))
          ev.set()
          print("subprocess joo_b ended")
      
      def main_event():
          qu = multiprocessing.Queue()
          ev = multiprocessing.Event()
          sub_a = multiprocessing.Process(target=joo_a, args=(qu, ev))
          sub_b = multiprocessing.Process(target=joo_b, args=(qu, ev,))
          sub_a.start()
          sub_b.start()
          # ev.set()
          sub_a.join()
          sub_b.join()
          while not qu.empty():
              print(qu.get())
      
      if __name__ == "__main__":
          main_event()

      5、共享内存方式通信

      (1) 共享变量

      子进程之间共存内存变量,要用 multiprocessing.Value(), Array() 来定义变量。 实际上是ctypes 类型,由multiprocessing.sharedctypes模块提供相关功能

      注意 使用 share memory 要考虑同抢等问题,释放等问题,需要手工实现。因此在使用共享变量时,建议使用Manager管程来管理这些共享变量。

      def  func(num):
          num.value=10.78   #子进程改变数值的值,主进程跟着改变
       
      if  __name__=="__main__":
      num = multiprocessing.Value("d", 10.0) 
      # d表示数值,主进程与子进程可共享这个变量。
      
          p=multiprocessing.Process(target=func,args=(num,))
          p.start()
          p.join()
       
          print(num.value)

      进程之间共享数据(数组型):

      import multiprocessing
       
      def  func(num):
          num[2]=9999   #子进程改变数组,主进程跟着改变
       
      if  __name__=="__main__":
          num=multiprocessing.Array("i",[1,2,3,4,5])   
      
          p=multiprocessing.Process(target=func,args=(num,))
          p.start() 
          p.join()
       
          print(num[:])

      (2) 共享内存 Shared_memory

      如果进程间需要共享对象数据,或共享内容,数据较大,multiprocessing 提供了SharedMemory类来实现进程间实时通信,不需要通过发消息,读写磁盘文件来实现,速度更快。
      注意:直接使用SharedMemory 存在着同抢、泄露隐患,应通过SharedMemory Manager 管程类来使用, 以确保内存安全。

      创建共享内存区:

      multiprocessing.shared_memory.SharedMemory(name=none, create=False, size=0)

      方法:
      父进程创建shared_memory 后,子进程可以使用它,当不再需要后,使用close(), 删除使用unlink()方法
      相关属性:
      获取内存区内容: shm.buf
      获取内存区名称: shm.name
      获取内存区字节数: shm.size

      示例:

      >>> from multiprocessing import shared_memory
      >>> shm_a = shared_memory.SharedMemory(create=True, size=10)
      >>> type(shm_a.buf)
      
      >>> buffer = shm_a.buf
      >>> len(buffer)
      10
      >>> buffer[:4] = bytearray([22, 33, 44, 55])  # Modify multiple at once
      >>> buffer[4] = 100                           # Modify single byte at a time
      >>> # Attach to an existing shared memory block
      >>> shm_b = shared_memory.SharedMemory(shm_a.name)
      >>> import array
      >>> array.array('b', shm_b.buf[:5])  # Copy the data into a new array.array
      array('b', [22, 33, 44, 55, 100])
      >>> shm_b.buf[:5] = b'howdy'  # Modify via shm_b using bytes
      >>> bytes(shm_a.buf[:5])      # Access via shm_a
      b'howdy'
      >>> shm_b.close()   # Close each SharedMemory instance
      >>> shm_a.close()
      >>> shm_a.unlink()  # Call unlink only once to release the shared memory

      3) ShareableList 共享列表

      sharedMemory类还提供了1个共享列表类型,这样就更方便了,进程间可以直接共享python强大的列表
      构建方法:
      multiprocessing.shared_memory.ShareableList(sequence=None, *, name=None)

      from multiprocessing import shared_memory
      >>> a = shared_memory.ShareableList(['howdy', b'HoWdY', -273.154, 100, None, True, 42])
      >>> [ type(entry) for entry in a ]
      [, , , , , , ]
      >>> a[2]
      -273.154
      >>> a[2] = -78.5
      >>> a[2]
      -78.5
      >>> a[2] = 'dry ice'  # Changing data types is supported as well
      >>> a[2]
      'dry ice'
      >>> a[2] = 'larger than previously allocated storage space'
      Traceback (most recent call last):
        ...
      ValueError: exceeds available storage for existing str
      >>> a[2]
      'dry ice'
      >>> len(a)
      7
      >>> a.index(42)
      6
      >>> a.count(b'howdy')
      0
      >>> a.count(b'HoWdY')
      1
      >>> a.shm.close()
      >>> a.shm.unlink()
      >>> del a  # Use of a ShareableList after call to unlink() is unsupported
      
      
      b = shared_memory.ShareableList(range(5))         # In a first process
      >>> c = shared_memory.ShareableList(name=b.shm.name)  # In a second process
      >>> c
      ShareableList([0, 1, 2, 3, 4], name='...')
      >>> c[-1] = -999
      >>> b[-1]
      -999
      >>> b.shm.close()
      >>> c.shm.close()
      >>> c.shm.unlink()

      6、共享内存管理器Manager

      Multiprocessing 提供了 Manager 内存管理器类,当调用1个Manager实例对象的start()方法时,会创建1个manager进程,其唯一目的就是管理共享内存, 避免出现进程间共享数据不同步,内存泄露等现象。

      其原理如下:

      Python multiprocessing模块中进程间通信的实现方式有哪些?

      Manager管理器相当于提供了1个共享内存的服务,不仅可以被主进程创建的多个子进程使用,还可以被其它进程访问,甚至跨网络访问。本文仅聚焦于由单一主进程创建的各进程之间的通信。

      1) Manager的主要数据结构

      相关类:multiprocessing.Manager
      子类有:

      • multiprocessing.managers.SharedMemoryManager

      • multiprocessing.managers.BaseManager

      支持共享变量类型:

      • python基本类型 int, str, list, tuple, list

      • 进程通信对象: Queue, Lock, Event,

      • Condition, Semaphore, Barrier ctypes类型: Value, Array

      2) 使用步骤

      1)创建管理器对象

      snm = Manager()
      snm = SharedMemoryManager()

      2)创建共享内存变量
      新建list, dict

      sl = snm.list(), snm.dict()

      新建1块bytes共享内存变量,需要指定大小

      sx = snm.SharedMemory(size)

      新建1个共享列表变量,可用列表来初始化

      sl = snm.ShareableList(sequence) 如
      sl = smm.ShareableList([‘howdy', b'HoWdY', -273.154, 100, True])

      新建1个queue, 使用multiprocessing 的Queue类型

      snm = Manager()
      q = snm.Queue()

      示例 :

      from multiprocessing import Process, Manager
      
      def f(d, l):
          d[1] = '1'
          d['2'] = 2
          d[0.25] = None
          l.reverse()
      
      if __name__ == '__main__':
          with Manager() as manager:
              d = manager.dict()
              l = manager.list(range(10))
      
              p = Process(target=f, args=(d, l))
              p.start()
              p.join()
      
              print(d)
              print(l)

      将打印

      {0.25: None, 1: '1', '2': 2}
      [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

      3) 销毁共享内存变量

      方法一:
      调用snm.shutdown()方法,会自动调用每个内存块的unlink()方法释放内存。或者 snm.close()
      方法二:
      使用with语句,结束后会自动释放所有manager变量

      >>> with SharedMemoryManager() as smm:
      ...     sl = smm.ShareableList(range(2000))
      ...     # Divide the work among two processes, storing partial results in sl
      ...     p1 = Process(target=do_work, args=(sl, 0, 1000))
      ...     p2 = Process(target=do_work, args=(sl, 1000, 2000))
      ...     p1.start()
      ...     p2.start()  # A multiprocessing.Pool might be more efficient
      ...     p1.join()
      ...     p2.join()   # Wait for all work to complete in both processes
      ...     total_result = sum(sl)  # Consolidate the partial results now in sl

      4) 向管理器注册自定义类型

      managers的子类BaseManager提供register()方法,支持注册自定义数据类型。如下例,注册1个自定义MathsClass类,并生成实例。

      from multiprocessing.managers import BaseManager
      
      class MathsClass:
          def add(self, x, y):
              return x + y
          def mul(self, x, y):
              return x * y
      
      class MyManager(BaseManager):
          pass
      
      MyManager.register('Maths', MathsClass)
      
      if __name__ == '__main__':
          with MyManager() as manager:
              maths = manager.Maths()
              print(maths.add(4, 3))         # prints 7
              print(maths.mul(7, 8))
      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发 Python
      相关文章 更多
      精品专题 更多
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      macOS软件

      正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

      IOS软件

      正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

      AI

      正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

      Mac软件 更多
      Aperty macOS版
      Aperty macOS版

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      火山引擎 网页版
      火山引擎 网页版

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      立刻MV 网页版
      立刻MV 网页版

      立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

      蛙蛙写作 网页版
      蛙蛙写作 网页版

      蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

      讯飞智作 网页版
      讯飞智作 网页版

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      超级简历WonderCV 网页版
      超级简历WonderCV 网页版

      超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

      音述AI 网页版
      音述AI 网页版

      音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

      AionClaw macOS版
      AionClaw macOS版

      AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

      Loomy macOS版
      Loomy macOS版

      Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

      AirBuddy 3 macOS版
      AirBuddy 3 macOS版

      AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

      AirServer macOS版
      AirServer macOS版

      AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

      AnyDesk macOS版
      AnyDesk macOS版

      AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

      WINDOWS 更多
      讯飞绘文 网页版
      讯飞绘文 网页版

      讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

      Maya(Autodesk Maya) Windows版
      Maya(Autodesk Maya) Windows版

      Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

      Aperty Windows版
      Aperty Windows版

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      火山引擎 网页版
      火山引擎 网页版

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      立刻MV 网页版
      立刻MV 网页版

      立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

      蛙蛙写作 网页版
      蛙蛙写作 网页版

      蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

      讯飞智作 网页版
      讯飞智作 网页版

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      超级简历WonderCV 网页版
      超级简历WonderCV 网页版

      超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

      音述AI 网页版
      音述AI 网页版

      音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

      AionClaw Windows版
      AionClaw Windows版

      AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

      Loomy Windows版
      Loomy Windows版

      Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

      AirServer Windows版
      AirServer Windows版

      AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。