python小练习15 -- 进程间通信

本文深入介绍了进程间通信的四种主要方式:管道、消息队列、共享内存和信号量。通过实例代码展示了如何在Python中实现这些通信机制,包括管道的双向通信、消息队列的队列操作、共享内存的读写以及信号量的同步控制。这些技术对于多进程间的协调和数据交换至关重要。
摘要由CSDN通过智能技术生成

进程间通信

  1. 必要性:进程间空间独立,资源不共享,此时在需要进程间数据传输时就需要特定的手段进行数据通信。
  2. 常用进程间通信方法:管道 消息队列 共享内存 信号 信号量 套接字

1、管道通信(Pipe)

通信原理:在内存中开辟管道空间,生成管道操作对象,多个进程使用通一个管道对象读写即可实现通信。

实现方法:

from multiprocess import Pipe

fd1,fd2 = Pipe(duplex=True)

功能:创建管道

参数:默认表示双向管道

如果False,表示单向管道

返回值:表示管道两端的读写对象

如果是双向管道均可读写

如果是单向管道fd1只读,fd2只写

fd.recv()

功能:从管道获取内容

返回值:获取到的数据

fd.send(data)

功能:向管道写入内容

参数:要写入的数据

示例代码:process_pipe.py

#!/usr/bin/python3
"""
    启动两个子进程,这两个子进程通过双向管道通信
"""
from multiprocess import Pipe, Process

fd1,fd2 = Pipe()    # 创建双向通信管道

def app1():
    print("app1 starts")
    print("app1 writes to app2")
    fd1.send('app1 data')
    data = fd1.recv()
    print('app1 receive data from app2:',data)

def app2():
    print("app2 starts")
    data = fd2.recv()
    print('app2 receive data from app1:',data)
    print('app2 send data to app1')
    fd2.send('app2 data')

p1 = Process(target=app1)  # 用单独进程运行app1函数
p2 = Process(target=app2)  # 用单独进程运行app2函数

p1.start()
p2.start()

p1.join()
p2.join()
print('main process finished')

测试结果:

[root@gyl-huawei python]# vim process_pipe.py
[root@gyl-huawei python]# ./process_pipe.py
app2 starts
app1 starts
app1 writes to app2
app2 receive data from app1: app1 data
app2 send data to app1
app1 receive data from app2: app2 data
main process finished

消息队列:

通信原理:在内存中建立队列模型,进程通过队列将消息存入,或者从队列去除完成进程间通信。

实现方法:

from multiprocess import Queue

q = Queue(maxsize=0)

功能:创建队列对象

参数:最多存放消息个数

返回值:队列对象。

q.put(data,[block,timeout])

功能:向队列存入消息

参数:data 要存入的内容

block 设置是否阻塞,False是非阻塞

timeout 超时检测

q.get([block,timeout])

功能:从队列取出消息

参数 block设置是否阻塞 False为非阻塞

timeout 超时检测

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

q.full() 判断队列是否为空

q.empty() 判断队列是否为空

q.qsize() 获取队列中消息个数

q.close() 关闭队列

示例代码: process_queue.py

#!/bin/env python3

from multiprocess import Process, Queue,Lock
from time import sleep
from random import randint

queue = Queue(5)   # 队列中最多放5个元素

def producer(pid): 
"""
    生产者:
    pid:标识生产者的号码
    产生一个1~100之间的随机数放入队列,如果队列满了,则睡眠2秒
"""
    flag = False
    while True:
        num = randint(1,100)
        sleep(1)

        lock.acquire()
        if not queue.full():
            queue.put(num)
            print("producer %d put (%d) to queue " % (pid, num))
        else:
            flag = True
        lock.release()
        if flag == True:
            flag = False
            sleep(2)

def consumer(cid):
"""
    从队列中取出一个数值,如果队列为空,则睡眠2秒
    cid:标识消费者的号码
"""
    flag = False
    while True:
        sleep(1.5)
        lock.acquire()
        if not queue.empty():
            num = queue.get()
            print("comsumer %d get (%d) from queue" % (cid, num))
        else:
            flag = True
        lock.release()
        if flag == True:
            flag = False
            sleep(2)


lock = Lock()
# 产生两个生产者,3个消费者
p1=Process(target=producer, args=(1,))
p2=Process(target=producer, args=(2,))
c1=Process(target=consumer, args=(1,))
c2=Process(target=consumer, args=(2,))
c3=Process(target=consumer, args=(3,))
go_on = True

tasks = [p1,p2,c1,c2,c3]
taskw = []
for task in tasks:
    task.deamon=True
    task.start()
    taskw.append(task)

for task in taskw:
    task.join()

print("main process completed")

测试结果:

[root@gyl-huawei python]# ./process_queue.py
producer 2 put (56) to queue
producer 1 put (27) to queue
comsumer 1 get (56) from queue
comsumer 2 get (27) from queue
producer 2 put (47) to queue
producer 1 put (64) to queue
producer 2 put (75) to queue
comsumer 1 get (47) from queue
producer 1 put (35) to queue
comsumer 2 get (64) from queue
producer 2 put (15) to queue
producer 1 put (84) to queue
comsumer 1 get (75) from queue
comsumer 2 get (35) from queue
producer 2 put (40) to queue
producer 1 put (38) to queue
comsumer 3 get (15) from queue
comsumer 1 get (84) from queue
producer 2 put (19) to queue
comsumer 2 get (40) from queue
producer 1 put (25) to queue
comsumer 3 get (38) from queue
^CProcess Process-4:

共享内存:

通信原理:在内存中开辟一块空间,进程可以写入内容和读取内容完成通信,但是每次内容会覆盖之前内容。

obj=Value(ctype, data)

功能:开辟共享内存

参数:ctype 表示共享内存空间类型 ‘i’ ‘f’ ‘c’ data 共享内存空间的初始数据

obj.value: 对该属性的修改查看即对共享内存读写

object = Array(ctype, data)

功能:开辟共享内存空间

参数:ctype 表示共享内存空间类型 data 整数则表示开辟空间的大小,其它数据类型表示开辟空间

返回值:共享内存对象。

Array共享内存读写:通过遍历obj可以得到每个值,直接可以通过索引获取

可以使用obj.value直接打印共享内存中的字节串。

代码示例:

#!/bin/env python3
"""
    共享内存示例:一个进程每次产生五个随机整数存入数组共享内存,另一个进程通过数组共享内存每次获取5个随机数并显示在终端。一个值共享内存协调两个进程的运行。
"""

from multiprocess import Process, Value, Array
from time import sleep
from random import randint


shm_value = Value('i',0)    # 值共享内存
shm_array= Array('i',5)     # 数组共享内存

def producer(shm_value,shm_array):
    while True:
        if shm_value.value == 1:
            sleep(1)
        else:
            vals = []
            for i in range(5):
                val = randint(1,100)
                shm_array[i] = val
                vals.append(val)
            print('producer puts values completed:',vals)
            shm_value.value = 1


def consumer(shm_value, shm_array):
    while True:
        if shm_value.value == 0:
            sleep(1)
        else:
            vals = []
            for i in range(5):
                vals.append(shm_array[i])
            print("consumer gets values:", vals)
            shm_value.value = 0

p1 = Process(target=producer,args=(shm_value,shm_array))
c1 = Process(target=consumer,args=(shm_value,shm_array))
p1.daemon = True
c1.daemon = True
p1.start()
c1.start()
#
p1.join()
c1.join()
print("main process completed")

测试:producer进程一次产生5个随机数,comsumer一个取出5个随机数,两个进程交替工作

[root@gyl-huawei python]# ./process_shm.py
producer puts values completed: [71, 43, 97, 43, 59]
consumer gets values: [71, 43, 97, 43, 59]
producer puts values completed: [50, 14, 97, 62, 87]
consumer gets values: [50, 14, 97, 62, 87]
producer puts values completed: [36, 81, 30, 70, 3]
consumer gets values: [36, 81, 30, 70, 3]
producer puts values completed: [80, 89, 49, 89, 89]
consumer gets values: [80, 89, 49, 89, 89]
producer puts values completed: [36, 71, 79, 74, 17]
^CProcess Process-2:

信号量

通信原理:给定一个数量对多个进程可见。多个进程可以操作该数量增减,并根据数量值决定自己的行为。

实现方法:

from multiprocess import Semaphore

sem = Semaphore(num)

功能:创建信号量对象。

参数:信号量的初始值。

返回值:信号量对象。

sem.acquire() 信号量减1 当信号量为0时阻塞。

sem.release() 将信号量加1

sem.get_value() 获取信号量数量。

代码示例:

#!/bin/env python3

from multiprocess import Process, Semaphore
from time import sleep


def func(i,sem):
    sem.acquire()
    print("function %d starting" % i)
    sleep(2)
    print("function %d finished!" % i)
    sem.release()


if __name__ == "__main__":
    sem = Semaphore(3)
    tasks = []
    for i in range(12):
        p = Process(target=func, args=(i+1,sem))
        tasks.append(p)
        p.deamon = True
        p.start()

    for task in tasks:
        task.join()

测试:每个进程只能获取信号量后才能运行,最多只能3个进程一起运行。

[root@gyl-huawei python]# ./process_sem.py  
function 5 starting
function 6 starting
function 2 starting
function 5 finished!
function 3 starting
function 6 finished!
function 7 starting
function 2 finished!
function 8 starting
function 3 finished!
function 7 finished!
function 8 finished!
function 9 starting
function 4 starting
function 1 starting
function 9 finished!
function 4 finished!
function 1 finished!
function 10 starting
function 11 starting
function 12 starting
function 10 finished!
function 11 finished!
function 12 finished!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值