Python进程间通信方式

 更新时间:2022年03月08日 09:07:37   作者:程序猿-张益达  
这篇文章主要介绍了Python进程间通信方式,进程彼此之间互相隔离,要实现进程间通信,主要通过队列方式,下文更多详细内容,需要的小伙伴可以参考一下

一、通信方式

进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块主要通过队列方式

队列:队列类似于一条管道,元素先进先出

需要注意的一点是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态

二、Queue介绍

创建队列的类(底层就是以管道和锁定的方式实现):

Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,

可以使用Queue实现多进程之间的数据传递。maxsize是队列中允许最大项数,省略则无大小限制。

三、方法介绍

  • def put(self, obj, block=True, timeout=None):插入数据到队列中,Block值默认为True,代表当队列已满时,会阻塞。如果block为False,则队列满会报异常Queue.Full,timeout表示会阻塞到指定时间,直到有剩余的空间供插入,如果时间超时,则报异常Queue.Full
  •  def get(self, block=True, timeout=None):从队列中取出数据,Block值默认为True,代表当队列为空时,会阻塞。如果block为False,则队列空会报异常Queue.Empty,timeout表示会等待到指定时间,直到取出数据,如果时间超时,则报异常Queue.Empty
  •  def empty(self): 判断队列是否为空,如果空返回True
  • def full(self): 判断队列是否已满,如果满返回True
  • def qsize(self): 返回队列的大小

应用举例:

from multiprocessing import Process, Manager
q = Manager().Queue(2)
q.put(1)
q.put(2,block=False,timeout=2)
def func():
    print(q.get())
 
p = Process(target=func)
print("size",q.qsize())
print("full",q.full())
p.start()
p.join()
print("empty",q.empty())
print("get", q.get())
print("get", q.get(block=False,timeout=2))

输出结果:

三、生产者和消费者模型

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。

为什么要使用生产者和消费者模式?

在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。

四、什么是生产者消费者模式

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯:

生产者,只需要往队列里面丢东西(生产者不需要关心消费者)

消费者,只需要从队列里面拿东西(消费者也不需要关心生产者)

阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

实现方式一:Queue

from multiprocessing import Process,Manager,active_children
import random
import queue
import time
 
class Producer(Process):
 
    def __init__(self,queue):
        super().__init__()
        self.queue = queue
 
    def run(self):
        for i in range(6):
            r = random.randint(0, 99)
            time.sleep(1)
            self.queue.put(r)
            print("add data{}".format(r))
 
class Consumer(Process):
 
    def __init__(self,queue):
        super().__init__()
        self.queue = queue
 
    def run(self):
        while True:
          if not self.queue.empty():
                data = self.queue.get()
                print("minus data{}".format(data))
 
 
if __name__ == '__main__':
    q = Manager().Queue() # 创建队列
    p = Producer(q)
    c = Consumer(q)
    p.start()
    c.start()
    print(active_children())  # 查看现有的进程
    p.join()
    c.join()
    print("结束")
 
 
>>>输出
[<ForkProcess(SyncManager-1, started)>, <Producer(Producer-2, started)>, <Consumer(Consumer-3, started)>]
add data83
minus data83
add data72
minus data72
add data8
minus data8
add data63
minus data63
add data75
minus data75
add data52
minus data52

实现方式二:利用JoinableQueue

JoinableQueue([maxsize]):一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。
JoinableQueue的实例除了与Queue对象相同的方法之外还具有:

     task_done():使用者使用此方法发出信号,表示get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常

     join():生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用task_done()方法为止

from multiprocessing import Process,JoinableQueue
import os
import time
import random
 
 
def print_log(msg, log_type="prod"):
    if log_type == 'prod':
        print("\033[32;1m%s\033[0m" %msg)
    elif log_type == 'con':
        print("\033[31;1m%s\033[0m" %msg)
 
def producer(q):
    """
    生产者
    :param q: 
    :return: 
    """
    for i in range(10):
        data = random.randint(1,200)
        time.sleep(2)
        q.put(data)  # 放入队列
        msg = "add data {}".format(data)
        print_log(msg)
    q.join()  # 生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。
    # 阻塞将持续到队列中的每个项目均调用q.task_done()方法为止
 
 
 
 
def consumer(q):
    """
    消费者
    :param q: 
    :return: 
    """
    while True:
        if not q.empty():
            time.sleep(5)
            data = q.get()
            msg = "minus data{}".format(data)
            print_log(msg,"con")
            q.task_done()  # q.get()的返回项目已经被处理
 
 
if __name__ == '__main__':
    q = JoinableQueue()
    prod = Process(target=producer, args=(q,))
    con = Process(target=consumer, args=(q,))
    con.daemon = True  # 设置为守护进程,但是不用担心,producer内调用q.join保证了consumer已经处理完队列中的所有元素
    # 开启进程
    prod.start()
    con.start()
 
    prod.join()  # 等待生产和消费完成,主线程结束
    print("结束")

输出结果:

到此这篇关于Python进程间通信方式的文章就介绍到这了,更多相关Python进程间通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于 Python opencv 使用中的 ValueError: too many values to unpack

    关于 Python opencv 使用中的 ValueError: too many values to unpack

    这篇文章主要介绍了关于 Python opencv 使用中的 ValueError: too many values to unpack,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • python实现折半查找和归并排序算法

    python实现折半查找和归并排序算法

    这篇文章主要介绍了python实现折半查找和归并排序算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • 对Python 字典元素进行删除的方法

    对Python 字典元素进行删除的方法

    这篇文章主要介绍了对Python 字典元素进行删除的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Python网络编程之Python编写TCP协议程序的步骤

    Python网络编程之Python编写TCP协议程序的步骤

    这篇文章主要介绍了Python网络编程编写TCP协议程序的开发步骤,通过实例代码介绍了TCP客户端程序开发,案例讲解多任务版TCP服务端程序开发,需要的朋友可以参考下
    2022-11-11
  • 超详细注释之OpenCV按位AND OR XOR和NOT

    超详细注释之OpenCV按位AND OR XOR和NOT

    这篇文章主要介绍了OpenCV按位AND OR XOR和NOT运算,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • python中%格式表达式实例用法

    python中%格式表达式实例用法

    在本篇文章里小编给大家整理的是一篇关于python中%格式表达式实例用法的相关内容,有兴趣的朋友们可以跟着学习下。
    2021-06-06
  • Python中不同图表的数据可视化的实现

    Python中不同图表的数据可视化的实现

    数据可视化是以图形格式呈现数据。它通过以简单易懂的格式汇总和呈现大量数据,帮助人们理解数据的重要性,并有助于清晰有效地传达信息。本文为大家准备了Python实现不同图表数据可视化的代码,需要的可以参考一下
    2022-08-08
  • python35种绘图函数详细总结

    python35种绘图函数详细总结

    Python有许多用于绘图的函数和库,比如Matplotlib,Plotly,Bokeh,Seaborn等,这只是一些常用的绘图函数和库,Python还有其他绘图工具,如Pandas、ggplot等,选择适合你需求的库,可以根据你的数据类型、图形需求和个人偏好来决定,本文给大家总结了python35种绘图函数
    2023-08-08
  • Pytorch backward报错2次访问计算图需要retain_graph=True的情况详解

    Pytorch backward报错2次访问计算图需要retain_graph=True的情况详解

    这篇文章主要介绍了Pytorch backward报错2次访问计算图需要retain_graph=True的情况,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • 详解python时间模块中的datetime模块

    详解python时间模块中的datetime模块

    这篇文章主要为大家介绍了python时间模块中的datetime模块,datetime模块的接口则更直观、更容易调用,想要了解datetime模块的朋友可以参考一下
    2016-01-01

最新评论