python不同程序间通信,Python多任务通信,之,进程,间通信

进程间通信

概念

:称进程间的数据交换(共享)为进程间通信(InterProcess Communication)。

必要性

:每个进程的空间独立,它们都有自己的内存地址、数据栈 以及 其他记录进程运行状态的辅助数据,这些进程的资源不可以直接共享,若需要进程间实现数据通信,则要借助特定的手段。

进程通信的常用方法

multiprocessing模块

1.消息队列(from multiprocessing import Queue)

2.管道(from multiprocessing import Pipe)

3.共享内存(from multiprocessing import Value, Array)

一、消息队列

1、通信原理

主进程在内存中建立队列结构,多个进程将消息存入队列,或从队列中取出消息,以此完成进程间通信。

2、实现方法

q = Queue([maxsize=0])

功能: 初始化队列对象

参数:最多存放的消息数量;若不指定或为负数,表示可接受的消息数量没有上限(直到内存尽头)

返回值:队列对象

q.put(item, [block=True, timeout=None])

功能:将item消息写入队列

参数:item 要存入的内容

block 默认为True,设置是否阻塞 ,False为非阻塞

timeout 超时检测

注解:

若block为默认值,timeout为空,消息队列无空间可用,此时进程阻塞在写入状态,直到消息队列有空间。若设置了timeout,则等待timeout秒,若还没空间,抛出异常Queue.Full

2.timeout默认值None,表示一直等待,不会超时

3.q.put_nowait(item)相当于q.put(item, False)

q.get([block=True, timeout=None])

功能:获取队列中的一条消息,然后将其从队列中移除

参数:block 默认为True,设置是否阻塞,False为非阻塞

timeout 超时检测

返回值: 返回获取到的内容

注解:

1.若block为默认值,timeout为空,消息队列为空,此时进程阻塞在读取状态,直到从消息队列中读到消息为止。若设置了timeout,则等待timeout秒,若还没读到任何消息,抛出异常queue.Empty

2.timeout默认值None,表示一直等待,不会超时

3.q.get_nowait()相当于q.get(False)

q.full() 判断队列是否为满;满返回True,否则False

q.empty() 判断队列是否为空;空返回True,否则False

q.qsize() 获取队列中的消息数量;

q.close() 关闭队列(不允许再往队列中放入消息,一旦队列为空,所占资源回收),通常情况下无需手动处理,而是自动回收。

from multiprocessing import Queue, Process

from time import sleep

from random import randint

def write_task(q):

"""向队列中写消息"""

for i in range(20):

x = randint(0, 100)

y = randint(0, 100)

q.put((x, y))

def read_task(q):

"""从队列中读消息"""

# =====================方法一=====================

sleep(1) # 休眠1秒的目的在于,避免读进程快于写进程

while not q.empty():

sleep(0.5) # 休眠的目的在于,防止在进程运行过程中队列为空

x, y = q.get(timeout=2)

print("%d + %d = %d" % (x, y, x+y))

# =====================方法二=====================

# while True:

# sleep(0.5)

# try:

# x, y = q.get(timeout=3)

# except Exception:

# break

# else:

# print("%d + %d = %d" % (x, y, x+y))

if __name__ == "__main__":

q = Queue(5) # 创建消息队列

pw = Process(target=write_task, args=(q, ))

pr = Process(target=read_task, args=(q, ))

pw.start()

pr.start()

pw.join()

pr.join()

二、管道(pipe)通信

1、通信原理

主进程在内存中开辟管道空间,并生成管道操作对象,多个进程再对管道操作对象进行写入或读取,以此完成进程间的通信。

2、实现方法

fd1, fd2 = Pipe(duplex=True)

功能:创建管道

参数:默认情况True表示双工(双向);若duplex=False表示单向管道

返回值:两个连接对象,分别表示管道两端,每个连接对象都有send()和recv()方法(相互之间的),也可通俗理解为两个读写对象

若是双向管道,则均可读写

若是单向管道,则fd1只读(只能用于接收消息),fd2只写(只能用于发送消息)

fd1.recv()

功能:从管道中获取数据并返回,该方法会一直阻塞直到接收到数据

fd1.send(data)

功能:想管道中写入数据,发送的数据对象必须是可序列化的,当数据量过大时(超过32MB),有可能引发ValueError异常。

fd1.poll([timeout])

功能:返回连接对象中是否有可以读取的数据

from multiprocessing import Process, Pipe

import os, time

# 单向管道中fd1只能读,fd2只能写

def fun(name, fd2):

# 子进程向管道中写入内容

fd2.send({name: os.getpid()})

if __name__ == "__main__":

fd1, fd2 = Pipe(False) # 创建管道

jobs = []

for i in range(5):

p = Process(target=fun, args=(i, fd2))

jobs.append(p)

p.start()

for i in range(5):

# 父进程读取管道

data = fd1.recv()

print(data)

for i in jobs:

i.join()

三、共享内存

1、通信原理

在共享内存上创建可被子进程继承的共享对象——ctypes对象。在内存中开辟空间,进程们在此空间上写入或读取内容,以完成进程间的通信。不同于消息队列和管道,共享内存没有对内存作结构化调整,只记录一个起始地址,每次写入的内容会覆盖之前的内容。

2、实现方法

obj = Value(ctype, data, lock=True)

功能:开辟共享内存空间

参数:ctype 表示共享内存的空间类型,如’i’,‘f’,‘c’,更多参数请参见下表

data 共享内存空间的初始数据内容

lock 递归锁,默认True,用于同步对于此值的访问操作

返回值:共享内存对象

obj.value 共享内存对象的属性,查看或修改该属性可对共享内存进行读写

类型吗

C语言类型

Python类型

所占字节数(至少)

‘c’

char

str(单字符的字符串)

1

‘b’

signed char

int

1

‘B’

unsigned char

int

1

‘u’

Py_UNICODE

str(unicode码的单字符字符串)

2

‘h’

signed short

int

2

‘H’

unsigned short

int

2

‘i’

signed int

int

2

‘I’

unsigned int

long

2

‘l’

signed long

int

4

‘L’

unsigned long

long

4

‘f’

float

float

4

‘d’

double

float

8

from multiprocessing import Value, Process

import time

import random

# 操作共享内存

def boy(money):

for i in range(30):

time.sleep(0.2)

money.value += random.randint(1, 1000)

def girl(money):

for i in range(30):

time.sleep(0.15)

money.value -= random.randint(100, 800)

if __name__ == "__main__":

# 创建共享内存

money = Value('i', 3000)

m = Process(target=boy, args=(money,))

g = Process(target=girl, args=(money, ))

m.start()

g.start()

m.join()

g.join()

# 获取共享内存值

print("一个月的余额:", money.value)

obj = Array(ctype, data, lock=True)

功能开辟共享内存空间

参数:ctype 表示共享内存的空间类型,如’i’,‘f’,‘c’,更多参数请参见上表

data 若是整数,则表示开辟空间的大小;

若是其他数据类型(一般为Python序列),则表示开辟空间存放的初始化数据

返回值:返回可迭代的共享内存对象

from multiprocessing import Process, Array

def fun(shm):

# 共享内存对象是可迭代的对象

for i in shm:

print(i)

# 替换共享内存中的值

# shm[1] = 1000

shm[0] = b'H'

if __name__ == "__main__":

# 创建共享内存

# 共享内存开辟5个整型列表空间

# shm = Array('i', 5) # 默认初始化值都为0

# shm[0] = 1;shm[1] = 2;shm[2] = 3;shm[3] = 4;shm[4] = 5 # 通过索引修改任意值

# 共享内存初始化整型数组数据[1,2,3]

# shm = Array('i', [1, 2, 3])

# 字节串

shm = Array('c', b'hello')

p = Process(target=fun, args=(shm, ))

p.start()

p.join()

# 父进程中查看对应的值

for i in shm:

print(i, end=" ")

print()

# 通过value属性访问字节串,且只能访问访问字节串

print(shm.value)

print(shm.raw)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在PyQt中使用joblib进行多进程进程间通信的方法如下[^1]: 1. 导入所需的模块: ```python from PyQt5.QtCore import QProcess, QSharedMemory, QBuffer, QIODevice from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtWidgets import QApplication from joblib import Parallel, delayed ``` 2. 创建一个自定义的类,继承自QProcess,并重写其run()方法: ```python class MyProcess(QProcess): def __init__(self, parent=None): super().__init__(parent) self.shared_memory = QSharedMemory() self.buffer = QBuffer() self.image = QImage() def run(self): # 在子进程中执行的代码 # 进程间通信的方式可以使用共享内存、管道等 # 这里以共享内存为例 self.shared_memory.setKey("image") self.shared_memory.attach() self.buffer.open(QIODevice.ReadWrite) self.buffer.setData(self.shared_memory.constData()) self.image.loadFromData(self.buffer.data()) self.buffer.close() self.shared_memory.detach() ``` 3. 在主进程中创建一个QApplication实例,并使用Parallel函数创建多个进程: ```python app = QApplication([]) processes = Parallel(n_jobs=-1)(delayed(run_process)() for _ in range(4)) ``` 4. 在子进程中执行任务,并将结果存储到共享内存中: ```python def run_process(): # 执行任务的代码 # 这里以处理图像为例 image = QImage("input.jpg") shared_memory = QSharedMemory() buffer = QBuffer() buffer.open(QIODevice.ReadWrite) image.save(buffer, "JPG") shared_memory.setKey("image") shared_memory.create(buffer.size()) shared_memory.lock() shared_memory.data().data().cast("char").move(0, buffer.data().size(), buffer.data().data()) shared_memory.unlock() buffer.close() process = MyProcess() process.start() process.waitForFinished() ``` 通过以上步骤,你可以在PyQt中使用joblib进行多进程进程间通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值