Python 从入门到实战37(进程间通信)

我们的目标是:通过这一套资料学习下来,可以熟练掌握python基础,然后结合经典实例、实践相结合,使我们完全掌握python,并做到独立完成项目开发的能力。

上篇文章我们讨论了通过multiprocessing模块创建进程操作的相关知识。今天学习一下进程间通信方式。

1、进程间能否直接共享信息

上一节我们学会了创建多个子进程,每个进程之间有什么关系呢?每个进程都有自己的地址空间、内存、数据栈以及其它记录其运行状态的辅助数据。我们举例说明进程之间能否之间共享信息:

定义一个全局变量,创建两个子进程对全局变量执行不同的操作。输出操作后的结果,查看:

#定义一个全局变量glo_num,创建两个子进程对全局变量执行不同的操作。输出操作后的结果

def plus():

print("************子进程1开始************")

global glo_num

glo_num = 200+100

print("glo_num is %d"%glo_num)

print("************子进程1结束************")

def minus():

print("************子进程2开始************")

global glo_num

glo_num = 200-100

print("glo_num is %d"%glo_num)

print("************子进程2结束************")

glo_num = 200

def main():

print("************主进程开始************")

print("父进程 的PID :%s。"%os.getpid())

p1 = Process(target=plus) #实例化进程1

p2 = Process(target=minus) #实例化进程2

p1.start() #开启进程1

p2.start()

p1.join() #等待p1进程结束

p2.join()

print("************主进程结束************")

if name=="main":

main()

输出结果参考:

我们可以看到全局变量200作为两个进程的初始值进行计算的。子进程之间没有共享信息。

如是修改:plus后面增加括号后,查看结果,进程就共享了信息。

p1 = Process(target=plus()) #实例化进程1,增加括号后

p2 = Process(target=minus()) #实例化进程2

2、多进程队列的使用

在Python中,队列是一种线性数据结构,遵循先进先出(FIFO)原则。Python的标准库中提供了queue模块,其中Queue类可以用来创建线程安全的队列。进程间就可以使用Queue来实现数据的传递

Queue常用的方法:

1)q=Queue(num) :初始化Queue()对象,num为指定的最大可接收消息数量,若num为空或者负数时,就代表可接收的消息数量没有上限,直到内存的尽头

2)Queue.qsize():返回当前队列包含的消息数量;

3)Queue.empty(): 如果队列为空,返回True ;否则返回False

  1. Queue.full():如果队列满了,返回True ;否则返回False;

5)Queue.get(block\[,timeout):获取队列中的一条消息,然后将其从队列中移除,block默认为True;如果block 使用默认值,且没有设置timeout(单位:s)消息队列为空,则此时程序会被阻塞。直到从消息读到消息位置,若设置了timeout,则会等待timeout 秒,若是还是没有任何消息,则抛出Queue.empty异常

如果block 使用False,消息队列为空,会立即抛出Queue.empty异常;

  1. Queue.get_nowait():相当于Queue.get(False);
  2. Queue.put(block\[,timeout):将item消息写入队列中,block默认为True;如果block 使用默认值,且没有设置timeout(单位:s),消息队列中已没有空间可写入,则此时程序会被阻塞。直到从空间可以写入消息为止,若设置了timeout,则会等待timeout 秒,若是还是没有任何写入空间,则抛出Queue.Full异常

如果block 使用False,消息队列没有空间可写入,会立即抛出Queue.Full异常;

  1. Queue.put_nowait(item):相当于Queue.put(item,False)

参考代码如下:

from multiprocessing import Queue

def main():

q = Queue(3) #初始化Queue 对象,最多可接收3条信息

q.put("message 1")

q.put("message 2")

print("队列还有空间吗?",q.full()) #队列是否满,返回False

q.put("message 3")

print("队列还有空间吗?", q.full()) #队列是否满,返回True

#尝试继续放入消息,如是没有空间写入,延时2秒后报错

try:

q.put("message",True,2)

except:

print("消息队列已满,现有消息数量:%s"%q.qsize())

#读取消息时,先判断消息队列是否为空

if not q.empty():

print("队列中消息为非空,读取消息")

for i in range(q.qsize()):

print(q.get_nowait()) #读取消息,无消息时报错不等待

#写入队列消息,先判断是否已满

if not q.full():

q.put_nowait("message 4")

print(q.get(True,5))

if name=="main":

main()

输出参考结果:

可以看到先进先出。

3、使用队列在进程间通信

举例说明:分别向队列中写入和读取数据

import time

from multiprocessing import Process

from multiprocessing import Queue

#向队列中写入数据

def write_fun(q1):

if not q1.full():

for i in range(4):

message = "消息" + str(i)

q1.put(message)

print("写入:%s"%message)

#从队列中读取数据

def read_fun(q2):

time.sleep(1)

while not q2.empty():

print("读取:%s"%q2.get(True,2))

def main():

print("----------父进程开始了------------")

q = Queue() #初始化Queue 对象,最多可接收3条信息

pw = Process(target=write_fun,args=(q,)) #实例化写入队列中的子进程,并且传递队列

pr = Process(target=read_fun,args=(q,))#实例化读取队列中的子进程,并且传递队列

pw.start() #启动子进程,进行写入

pr.start()

pw.join() #等待子进程执行结束

pr.join()

print("----------父进程结束了------------")

if name=="main":

main()

输出结果参考:

今天先写学习到这里了,每天进步一点点。明天也要加油啊!

相关推荐
颜颜yan_9 小时前
ESP-IDF 鸿蒙 PC 适配全记录:打通 Python、构建工具链与 ESP32-P4 固件生成
python·华为·harmonyos
言乐69 小时前
Python加速器4跨境网络加速器
运维·服务器·开发语言·网络·python
weixin_440730509 小时前
线程02-并发串行-互斥锁-Semaphore-Event
python·thread
金金计较.9 小时前
Go语言-3
java·开发语言·golang
张小凡vip10 小时前
python--爬虫--经验积累的遇到的坑
开发语言·爬虫·python
毕业设计70311 小时前
(免费领源码) 基于微信小程序的预制菜商城的设计与实现25172-java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
vue.js·python·mysql·微信小程序·pycharm·微信开发者工具·推荐算法
xifangge202511 小时前
AGENTS.md 怎么写?涵盖 Java、Python、Vue、Go 的 8 套开箱即用模板
java·vue.js·python
Wang's Blog11 小时前
Java框架快速入门: Spring Security+OAuth2之云服务集成与多因子认证设计
java·开发语言·spring
门思科技11 小时前
LoRaWAN 网络容量估算:一个 SX1302 网关到底能带多少设备
开发语言·网络·php
大草原的小灰灰11 小时前
Python基础语法
开发语言·python