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

Python进程间的通信方式是什么

Jun 03, 2023 pm 02:09 PM
python

什么是进程的通信

这里举一个通信机制的例子:我们都很熟悉通信这个词,比如一个人想给他的女友打电话。一旦通话建立,便会形成一个隐式的队列(请注意这个术语)。此时这个人就会通过对话的方式不停的将信息告诉女友,而这个人的女友也是在倾听着。我认为在大多数情况下,情况可能是倒过来的。

这里可以将他们两个人比作是两个进程,"这个人"的进程需要将信息发送给"女友"的进程,就需要一个队列的帮助。由于女友需要时刻接收队列中的信息,因此她可以同时进行其他事情,这意味着两个进程之间的通信主要依赖于队列。

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

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

队列的创建 - 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()
登录后复制

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

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

报错截图示例如下:

Python进程间的通信方式是什么

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

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

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

解决示意图如下:

Python进程间的通信方式是什么

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

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

运行结果如下:

Python进程间的通信方式是什么

批量给 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()
登录后复制

运行结果如下:

Python进程间的通信方式是什么

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

小节

在这一章节,我们成功运用队列实现了跨进程通信,同时也掌握了队列的操作技巧。一个队列中,有一端(这里我们演示的是 send端)通过 put方法实现添加相关的信息,另一端使用 get 方法获取相关的信息;两个进程相互配合达到一个进程通信的效果。

除了队列,进程之间还可以使用管道、信号量和共享内存等方式进行通信,如果您感兴趣,可以了解一下这些方法。可以自行拓展一下。

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

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

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

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

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

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

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

一种重写方式是:在操作系统内核中建立一个队列,队列中包含多个数据报元素,多个进程可以通过特定句柄来访问该队列。消息队列可以用来将数据从一个进程发送到另一个进程。每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型。消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的,每个消息队列的总的字节数是有上限的,系统上消息队列的总数也有一个上限

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

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

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

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

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

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

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

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

以上是Python进程间的通信方式是什么的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP和Python:代码示例和比较 PHP和Python:代码示例和比较 Apr 15, 2025 am 12:07 AM

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。

CentOS上PyTorch的GPU支持情况如何 CentOS上PyTorch的GPU支持情况如何 Apr 14, 2025 pm 06:48 PM

在CentOS系统上启用PyTorchGPU加速,需要安装CUDA、cuDNN以及PyTorch的GPU版本。以下步骤将引导您完成这一过程:CUDA和cuDNN安装确定CUDA版本兼容性:使用nvidia-smi命令查看您的NVIDIA显卡支持的CUDA版本。例如,您的MX450显卡可能支持CUDA11.1或更高版本。下载并安装CUDAToolkit:访问NVIDIACUDAToolkit官网,根据您显卡支持的最高CUDA版本下载并安装相应的版本。安装cuDNN库:前

Python vs. JavaScript:社区,图书馆和资源 Python vs. JavaScript:社区,图书馆和资源 Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

docker原理详解 docker原理详解 Apr 14, 2025 pm 11:57 PM

Docker利用Linux内核特性,提供高效、隔离的应用运行环境。其工作原理如下:1. 镜像作为只读模板,包含运行应用所需的一切;2. 联合文件系统(UnionFS)层叠多个文件系统,只存储差异部分,节省空间并加快速度;3. 守护进程管理镜像和容器,客户端用于交互;4. Namespaces和cgroups实现容器隔离和资源限制;5. 多种网络模式支持容器互联。理解这些核心概念,才能更好地利用Docker。

minio安装centos兼容性 minio安装centos兼容性 Apr 14, 2025 pm 05:45 PM

MinIO对象存储:CentOS系统下的高性能部署MinIO是一款基于Go语言开发的高性能、分布式对象存储系统,与AmazonS3兼容。它支持多种客户端语言,包括Java、Python、JavaScript和Go。本文将简要介绍MinIO在CentOS系统上的安装和兼容性。CentOS版本兼容性MinIO已在多个CentOS版本上得到验证,包括但不限于:CentOS7.9:提供完整的安装指南,涵盖集群配置、环境准备、配置文件设置、磁盘分区以及MinI

CentOS上PyTorch的分布式训练如何操作 CentOS上PyTorch的分布式训练如何操作 Apr 14, 2025 pm 06:36 PM

在CentOS系统上进行PyTorch分布式训练,需要按照以下步骤操作:PyTorch安装:前提是CentOS系统已安装Python和pip。根据您的CUDA版本,从PyTorch官网获取合适的安装命令。对于仅需CPU的训练,可以使用以下命令:pipinstalltorchtorchvisiontorchaudio如需GPU支持,请确保已安装对应版本的CUDA和cuDNN,并使用相应的PyTorch版本进行安装。分布式环境配置:分布式训练通常需要多台机器或单机多GPU。所

CentOS上PyTorch版本怎么选 CentOS上PyTorch版本怎么选 Apr 14, 2025 pm 06:51 PM

在CentOS系统上安装PyTorch,需要仔细选择合适的版本,并考虑以下几个关键因素:一、系统环境兼容性:操作系统:建议使用CentOS7或更高版本。CUDA与cuDNN:PyTorch版本与CUDA版本密切相关。例如,PyTorch1.9.0需要CUDA11.1,而PyTorch2.0.1则需要CUDA11.3。cuDNN版本也必须与CUDA版本匹配。选择PyTorch版本前,务必确认已安装兼容的CUDA和cuDNN版本。Python版本:PyTorch官方支

centos如何安装nginx centos如何安装nginx Apr 14, 2025 pm 08:06 PM

CentOS 安装 Nginx 需要遵循以下步骤:安装依赖包,如开发工具、pcre-devel 和 openssl-devel。下载 Nginx 源码包,解压后编译安装,并指定安装路径为 /usr/local/nginx。创建 Nginx 用户和用户组,并设置权限。修改配置文件 nginx.conf,配置监听端口和域名/IP 地址。启动 Nginx 服务。需要注意常见的错误,如依赖问题、端口冲突和配置文件错误。性能优化需要根据具体情况调整,如开启缓存和调整 worker 进程数量。

See all articles