Python语法学习之进程间的通信方式

目录
  • 什么是进程的通信
    • 队列的创建 - multiprocessing
    • 进程之间通信的方法
  • 进程间的通信 - 队列演示案例
    • 批量给 send 函数加入数据
  • 小节
    • 进程间通信的其他方式 - 补充

什么是进程的通信

这里举一个例子接介绍通信的机制:通信 一词大家并不陌生,比如一个人要给他的女友打电话。当建立了通话之后,在这个通话的过程中就是建立了一条隐形的 队列 (记住这个词)。此时这个人就会通过对话的方式不停的将信息告诉女友,而这个人的女友也是在倾听着。(嗯…我个人觉得大部分情况下可能是反着来的)。

这里可以将他们两个人比作是两个进程,"这个人"的进程需要将信息发送给"女友"的进程,就需要一个队列的帮助。而女友需要不停的接收队列的信息,可以做一些其他的事情,所以两个进程之间的通信主要依赖于队列。

这个队列可以支持发送消息与接收消息,“这个人"负责发送消息,反之"女友” 负责的是接收消息。

既然队列才是重点,那么来看一下队列要如何创建。

队列的创建 - multiprocessing

依然使用 multiprocessing 模块,调用该模块的 Queue 函数来实现队列的创建。

函数名 介绍 参数 返回值
Queue 队列的创建 mac_count 队列对象

Queue 函数功能介绍:调用 Queue 可以创建队列;它有一个参数 mac_count 代表队列最大可以创建多少信息,如果不传默认是无限长度。实例化一个队列对象之后,需要操作这个队列的对象进行放入与取出数据。

进程之间通信的方法

函数名 介绍 参数 返回值
put 将消息放入队列 message
get 获取队列消息 str

put 函数功能介绍:将数据传入。它有一个参数 message ,是一个字符串类型。

get 函数功能介绍:用来接收队列中的数据。(其实这里就是一个常用的json场景,有很多的数据传输都是 字符串 的,队列的插入与获取就是使用的字符串,所以 json 就非常适用这个场景。)

接下来就来练习一下 队列的使用 。

进程间的通信 - 队列演示案例

代码示例如下:

# coding:utf-8

import json
import multiprocessing

class Work(object):     # 定义一个 Work 类
    def __init__(self, queue):      # 构造函数传入一个 '队列对象' --> queue
            self.queue = queue

    def send(self, message):        # 定义一个 send(发送) 函数,传入 message
                                    # [这里有个隐藏的bug,就是只判断了传入的是否字符串类型;如果传入的是函数、类、集合等依然会报错]
        if not isinstance(message, str):    # 判断传入的 message 是否为字符串,若不是,则进行 json 序列化
            message = json.dumps(message)
        self.queue.put(message)     # 利用 queue 的队列实例化对象将 message 发送出去

    def receive(self):      # 定义一个 receive(接收) 函数,不需传入参数,但是因为接收是一个源源不断的过程,所以需要使用 while 循环
        while 1:
            result = self.queue.get()   # 获取 '队列对象' --> queue 传入的message
                                        # 由于我们接收的 message 可能不是一个字符串,所以要进程异常的捕获
            try:                        # 如果传入的 message 符合 JSON 格式将赋值给 res ;若不符合,则直接使用 result 赋值 res
                res = json.loads(result)
            except:
                res = result
            print('接收到的信息为:{}'.format(res))

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    work = Work(queue)
    send = multiprocessing.Process(target=work.send, args=({'message': '这是一条测试的消息'},))
    receive = multiprocessing.Process(target=work.receive)

    send.start()
    receive.start()

使用队列建立进程间通信遇到的异常

但是这里会出现一个 报错,如下图:

报错截图示例如下:

这里的报错提示是 文件没有被发现的意思 。其实这里是我们使用 队列做 put() 和 get()的时候 有一把无形的锁加了上去,就是上图中圈中的 .SemLock 。我们不需要去关心造成这个错误的具体原因,要解决这个问题其实也很简单。

FileNotFoundError: [Errno 2] No such file or directory 异常的解决

我们只需要给 send 或者 receive 其中一个子进程添加 join 阻塞进程即可,理论上如此。但是我们的 receive子进程是一个 while循环,它会一直执行,所以只需要给 send 子进程加上一个 join 即可。

解决示意图如下:

PS:虽然解决了报错问题,但是程序没有正常退出。

实际上由于我们的 receive 进程是个 while循环,并不知道要处理到什么时候,没有办法立刻终止。所以我们需要在 receive 进程 使用 terminate() 函数终结接收端。

运行结果如下:

批量给 send 函数加入数据

新建一个函数,写入 for循环 模拟批量添加要发送的消息

然后再给这个模拟批量发送数据的函数添加一个线程。

示例代码如下:

# coding:utf-8

import json
import time
import multiprocessing

class Work(object):     # 定义一个 Work 类
    def __init__(self, queue):      # 构造函数传入一个 '队列对象' --> queue
            self.queue = queue

    def send(self, message):        # 定义一个 send(发送) 函数,传入 message
                                    # [这里有个隐藏的bug,就是只判断了传入的是否字符串类型;如果传入的是函数、类、集合等依然会报错]
        if not isinstance(message, str):    # 判断传入的 message 是否为字符串,若不是,则进行 json 序列化
            message = json.dumps(message)
        self.queue.put(message)     # 利用 queue 的队列实例化对象将 message 发送出去

    def send_all(self):             # 定义一个 send_all(发送)函数,然后通过for循环模拟批量发送的 message
        for i in range(20):
            self.queue.put('第 {} 次循环,发送的消息为:{}'.format(i, i))
            time.sleep(1)

    def receive(self):      # 定义一个 receive(接收) 函数,不需传入参数,但是因为接收是一个源源不断的过程,所以需要使用 while 循环
        while 1:
            result = self.queue.get()   # 获取 '队列对象' --> queue 传入的message
                                        # 由于我们接收的 message 可能不是一个字符串,所以要进程异常的捕获
            try:                        # 如果传入的 message 符合 JSON 格式将赋值给 res ;若不符合,则直接使用 result 赋值 res
                res = json.loads(result)
            except:
                res = result
            print('接收到的信息为:{}'.format(res))

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    work = Work(queue)
    send = multiprocessing.Process(target=work.send, args=({'message': '这是一条测试的消息'},))
    receive = multiprocessing.Process(target=work.receive)
    send_all = multiprocessing.Process(target=work.send_all,)

    send_all.start()    # 这里因为 send 只执行了1次,然后就结束了。而 send_all 却要循环20次,它的执行时间是最长的,信息也是发送的最多的
    send.start()
    receive.start()

    # send.join()       # 使用 send 的阻塞会造成 send_all 循环还未结束 ,receive.terminate() 函数接收端就会终结。
    send_all.join()     # 所以我们只需要阻塞最长使用率的进程就可以了
    receive.terminate()

运行结果如下:

从上图中我们可以看到 send 与 send_all 两个进程都可以通过 queue这个实例化的 Queue 对象发送消息,同样的 receive接收函数也会将两个进程传入的 message 打印输出出来。

小节

该章节我们通过队列的方式实现了进程间通信的方法,并且了解了队列的使用方法。一个队列中,有一端(这里我们演示的是 send端)通过 put方法实现添加相关的信息,另一端使用 get 方法获取相关的信息;两个进程相互配合达到一个进程通信的效果。

其实进程之间的通信不仅仅只有队列这一种方式,感兴趣的话还可以通过 管道、信号量、共享内存的方式来实现。可以自行拓展一下。

进程间通信的其他方式 - 补充

python提供了多种进程通信的方式,包括信号,管道,消息队列,信号量,共享内存,socket等

主要Queue和Pipe这两种方式,Queue用于多个进程间实现通信,Pipe是两个进程的通信。

1.管道:分为匿名管道和命名管道

匿名管道:在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,一般使用fock函数实现父子进程的通信

命名管道:在内存中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,没有血缘关系的进程也可以进程间通信

特点:面向字节流;生命周期随内核;自带同步互斥机制;半双工,单向通信,两个管道实现双向通信

2.消息队列:在内核中创建一个队列,队列中每个元素是一个数据报,不同的进程可以通过句柄去访问这个队列。消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法。每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型。消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的,每个消息队列的总的字节数是有上限的,系统上消息队列的总数也有一个上限

特点:消息队列可以被认为是一个全局的一个链表,链表节点中存放着数据报的类型和内容,有消息队列的标识符进行标记;消息队列允许一个或多个进程写入或读取消息;消息队列的生命周期随内核;消息队列可实现双向通信

3.信号量:在内核中创建一个信号量集合(本质上是数组),数组的元素(信号量)都是1,使用P操作进行-1,使用V操作+1

P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该程序的执行

V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1

PV操作用于同一个进程,实现互斥;PV操作用于不同进程,实现同步

功能:对临界资源进行保护

4.共享内存:将同一块物理内存一块映射到不同的进程的虚拟地址空间中,实现不同进程间对同一资源的共享。共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式

特点:不同从用户态到内核态的频繁切换和拷贝数据,直接从内存中读取就可以;共享内存是临界资源,所以需要操作时必须要保证原子性。使用信号量或者互斥锁都可以.

以上就是Python语法学习之进程间的通信方式的详细内容,更多关于Python进程通信方式的资料请关注我们其它相关文章!

(0)

相关推荐

  • python中进程间通信详细介绍

    目录 进程间通信(IPC) 管道通信(Pipe) 1.通信原理 2. 实现方法 共享内存 1.通信原理 2.实现方法 信号量(信号灯集) 1.通信原理 2. 实现方法 3.代码演示 进程间通信(IPC) 必要性 进程间空间独立,资源不共享,此时在需要进程间数据传输时就需要特定的手段进行数据通信 常用进程间通信方法 管道 消息队列 共享内存 型号 信号量 套接字 管道通信(Pipe) 1.通信原理 在内存中开辟管道空间,生成管道操作对象,多个进程使用同一个管道对象进行读写即可实现通信 代码演示(w

  • Python进程间通信方式

    目录 一.通信方式 二.Queue介绍 三.方法介绍 三.生产者和消费者模型 四.什么是生产者消费者模式 实现方式一:Queue 实现方式二:利用JoinableQueue 一.通信方式 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块主要通过队列方式 队列:队列类似于一条管道,元素先进先出 需要注意的一点是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态 二.Queue介绍 创建队列的类(底层就是以管道和锁定的方式实现): Queue

  • Python进程间通信用法实例

    本文实例讲述了Python进程间通信用法.分享给大家供大家参考.具体如下: #!/usr/bin/env python # -*- coding=utf-8 -*- import multiprocessing def counsumer(input_q): while True: item = input_q.get() #处理项目 print item #此处替换为有用的工作 #发出信号通知任务完成 input_q.task_done() def producer(sequence,outp

  • Python进程间的通信一起来了解下

    目录 通信方式 Queue介绍: 生产者和消费者模型 为什么要使用生产者和消费者模式 什么是生产者消费者模式 实现方式一:Queue 实现方式二:利用JoinableQueue 总结 通信方式 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块主要通过队列方式 队列:队列类似于一条管道,元素先进先出 需要注意的一点是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态 Queue介绍: 创建队列的类(底层就是以管道和锁定的方式实现): Que

  • Python的进程间通信详解

    目录 进程概述 队列简介 多进程队列的使用 使用队列在进程间通信 总结 进程概述 ​ 进程(Process)是计算机中已运行程序的实体.进程与程序不同,程序本身只是指令.数据及器组织形式的描述,进程才是程序(那些指令和数据)的真正运行实体.例如在没有打开QQ时,QQ只是程序.打开以后,操作系统为QQ开启一个进程.再打开一个QQ,则又开启一个进程. ​ 那么在多进程中,每个进程之间是什么关系呢?其实每个进程都有自己的地址空间.内存.数据栈以及其他记录其运行状态的辅助数据.下通过一个例子验证一下进程

  • Python语法学习之进程间的通信方式

    目录 什么是进程的通信 队列的创建 - multiprocessing 进程之间通信的方法 进程间的通信 - 队列演示案例 批量给 send 函数加入数据 小节 进程间通信的其他方式 - 补充 什么是进程的通信 这里举一个例子接介绍通信的机制:通信 一词大家并不陌生,比如一个人要给他的女友打电话.当建立了通话之后,在这个通话的过程中就是建立了一条隐形的 队列 (记住这个词).此时这个人就会通过对话的方式不停的将信息告诉女友,而这个人的女友也是在倾听着.(嗯…我个人觉得大部分情况下可能是反着来的)

  • Python语法学习之进程的创建与常用方法详解

    目录 进程的创建模块 - multiprocessing 创建进程函数 - Process 进程的常用方法 start 函数 join 函数 kill 函数 与 is_alive 函数 进程的相关问题 该章节我们来学习一下在 Python 中去创建并使用多进程的方法,通过学习该章节,我们将可以通过创建多个进程来帮助我们提高脚本执行的效率.可以认为缩短脚本执行的时间,就是提高执行我们脚本的效率.接下来让我们都看一下今天的章节知识点都有哪些? 进程的创建模块 - multiprocessing 创建

  • Python语法学习之进程池与进程锁详解

    目录 进程池 什么是进程池 进程池的创建模块 - multiprocessing 创建进程池函数 - Pool 进程池的常用方法 apply_async 函数演示案例 close 函数与 join 函数 演示 进程锁 进程锁的概念 进程锁的加锁与解锁 NICE!大家好,在上一章节,我们学习了 multiprocessing 模块 的关于进程的创建与进场常用的方法的相关知识. 通过在一个主进程下创建多个子进程可以帮助我们加速程序的运行,并且提高工作效率.不过上一章节文末我们也说过进程的问题,由于每

  • Python语法学习之线程的创建与常用方法详解

    目录 线程的创建与使用 线程的创建 -threading 线程对象的常用方法 线程演示案例 线程的问题 线程的创建与使用 在Python中有很多的多线程模块,其中 threading 模块就是比较常用的.下面就来看一下如何利用 threading 创建线程以及它的常用方法. 线程的创建 -threading 函数名 介绍 举例 Thread 创建线程 Thread(target, args) Thread 的动能介绍:通过调用 threading 模块的 Thread 类来实例化一个线程对象:它

  • Python使用文件锁实现进程间同步功能【基于fcntl模块】

    本文实例讲述了Python使用文件锁实现进程间同步功能.分享给大家供大家参考,具体如下: 简介 在实际应用中,会出现这种应用场景:希望shell下执行的脚本对某些竞争资源提供保护,避免出现冲突.本文将通过fcntl模块的文件整体上锁机制来实现这种进程间同步功能. fcntl系统函数介绍 Linux系统提供了文件整体上锁(flock)和更细粒度的记录上锁(fcntl)功能,底层功能均可由fcntl函数实现. 首先来了解记录上锁.记录上锁是读写锁的一种扩展类型,它可用于有亲缘关系或无亲缘关系的进程间

  • Python语法学习之正则表达式的量词汇总

    目录 正则表达式中的符号 示例 - 1 示例 - 2 示例 - 3 示例 - 4 示例 - 5 示例 - 6 示例 - 7 示例 - 8 组的概念 贪婪模式与非贪婪模式 正则表达式中的符号 符号 描述 re1 | re2 匹配正则表达式 re1 或者 re2 :re1 与 re2 代表两个匹配的字符串信息 ^ 匹配字符串起始部分 $ 匹配字符串终止部分(也就是末尾部分) * 匹配0次或者多次前面出现的正则表达式 + 匹配1次或者多次前面出现的正则表达式 {N} 匹配 N 次前面出现的正则表达式

  • Python语法学习之正则表达式的使用详解

    目录 正则表达式中的特殊字符 正则表达式的使用 正则小案例 - 1 正则小案例 - 2 正则小案例 - 3 要想成功的进行字符串的匹配需要使用到正则表达式模块,正则表达式匹配规则以及需要被匹配的字符串.在这三个条件中,模块与字符串都是准备好的,只有匹配规则异常的灵活,而今天这个章节就是认识一下正则表达式中的特殊字符,通过这些字符就可以针对我们想要的数据进行匹配. 正则表达式中的特殊字符 特殊字符 描述 \d 匹配任何十进制的数字,与[0-9]一致 \D 匹配任意非数字 \w 匹配任何字母数字下划

  • python语法学习之super(),继承与派生

    目录 1 什么是继承? 2 继承的规则 3 继承原理 4 多继承属性查询顺序 5 查找流程 属性查找 6 继承概念的实现 7 私有属性私有方法在继承中的表现 8 派生类 9 属性的覆盖(派生属性) 10 父类属性(方法)的重用 11 继承派生机制的作用 12 Super() 1 什么是继承? 继承是一种创建新类的方式: 在Python中,新建的类可以继承一个或多个父类,新建的类可称为子类或派生类,父类又可称为基类或超类. 继承可以用来解决类与类之间的代码重用性问题: class ParentCl

  • python 进程间数据共享multiProcess.Manger实现解析

    一.进程之间的数据共享 展望未来,基于消息传递的并发编程是大势所趋 即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合,通过消息队列交换数据. 这样极大地减少了对使用锁定和其他同步手段的需求,还可以扩展到分布式系统中. 但进程间应该尽量避免通信,即便需要通信,也应该选择进程安全的工具来避免加锁带来的问题. 以后我们会尝试使用数据库来解决现在进程之间的数据共享问题. 1.1 Manager模块介绍 虽然进程间数据独立,但可以通过Manager实现数据共享,事实上Manager的功能远不止于

  • Python multiprocessing.Manager介绍和实例(进程间共享数据)

    Python中进程间共享数据,处理基本的queue,pipe和value+array外,还提供了更高层次的封装.使用multiprocessing.Manager可以简单地使用这些高级接口. Manager()返回的manager对象控制了一个server进程,此进程包含的python对象可以被其他的进程通过proxies来访问.从而达到多进程间数据通信且安全. Manager支持的类型有list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaph

随机推荐