python进程间通信

python进程间通信主要应用于,多进程时,进程间数据的交换和传递。
进程间通信主要有5中方式:
1、管道
2、消息队列
3、共享内存
4、信号
5、套接字

linux文件类型

  • 普通文件类型 :-
    Linux中最多的一种文件类型, 包括 纯文本文件(ASCII);二进制文件(binary);数据格式的文件(data);各种压缩文件.第一个属性为 [-]

  • 目录文件 :d
    就是目录, 能用 # cd 命令进入的。第一个属性为 [d],例如 [drwxrwxrwx]

  • 块设备文件 :b
    块设备文件 : 就是存储数据以供系统存取的接口设备,简单而言就是硬盘。例如一号硬盘的代码是 /dev/hda1等文件。第一个属性为 [b]

  • 字符设备 :c
    字符设备文件:即串行端口的接口设备,例如键盘、鼠标等等。第一个属性为 [c]

  • 套接字文件 ?
    这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。第一个属性为 [s],最常在 /var/run目录中看到这种文件类型

  • 管道文件 :p
    FIFO也是一种特殊的文件类型,它主要的目的是,解决多个程序同时存取一个文件所造成的错误。FIFO是first-in-first-out(先进先出)的缩写。第一个属性为 [p]
    1、管道
    multiprocessing 中的 Pipe 函数
    p,q=Pipe(duplex)
    功能 : 创建一个管道
    参数 :
    duplex 默认为 True 表示管道为双向管道
    如果设置为False 则表示管道为单向管道
    返回值
    返回两个管道流对象,分别表示管道的两端
    如果参数为True(默认) 两个对象均可发送接受
    如果为False时 则第一个对象只能接受,第二个对象只能发送

     from multiprocessing import Process,Pipe 
     import os,time
     #创建管道对象
     #当参数为False的时候child只能recv parent只能send
      child_conn,parent_conn = Pipe(False)
     child_conn,parent_conn = Pipe()
     #子进程函数
     def fun(name):
         time.sleep(1)
         #发送一个字符串到管道
         child_conn.send('hello' + str(name))
         print(os.getppid(),"----",os.getpid())
     jobs = []
     #创建5个子进程
     for i in range(5):
         p = Process(target = fun,args = (i,))
         jobs.append(p)
         p.start()
     for i in range(5):
         data = parent_conn.recv()
         print(data)
     for i in jobs:
         i.join()
    

2、消息队列
multiprocessing — 》 Queue
在内存中开辟一个队列模型,用来存放消息。任何拥有队列对象的进程都可以进行消息的存放和取出
q=Queue(maxsize = 0)
功能 : 创建一个消息队列对象
参数 : maxsize 默认为0 表示消息队列可以存放的消息有 系统自动分配的空间而定
> 0 正整数 表示队列中最多存放多少条消息
返回值 : 消息队列对象

q.put()
向消息队列中存放一条消息,当消息队列满的时候,会阻塞
存放的消息类型可以使数字列表,字串等
q.full()
判断队列是否为满,如果满则返回True 否则返回False
q.qsize()
查看当前队列中消息数量
q.get()
获取消息,每次获取一条,当消息队列为空是,则阻塞
q.empty()
消息队列为空则返回True 不为空返回False
put get 中block参数和timeout参数
block 默认为True 表示两个函数都是阻塞函数
如果设置为False则表示不阻塞
timeout 当block设置为True的时候表示超时等待时间

from multiprocessing import Process,Queue 
import time 
q = Queue()
def fun(name):
    time.sleep(1)
    q.put("hello" + str(name))
jobs = []
for i in range(10):
    p = Process(target = fun,args =(i,))
    jobs.append(p)
    p.start()
for i in jobs:
    i.join()
while not q.empty():
    print(q.get())

3、共享内存
在内存中开辟一段内存空间存储数据,每次存储的内容会覆盖上次的内容。由于没有对内存进行格式化的修饰所以存取速度块效率高

from multiprocessing import Value,Array
obj = Value(ctype,obj)
功能 : 开辟共享内存
参数 : ctype 要转变的c的类型
obj 要写入共享内存的初始值
obj.value 属性为获取共享内存中的值
obj = Array(ctype,obj)
功能 : 开辟一个共享内存空间
参数 : 要转换的c的类型
obj : 放入共享内存中的数据,是一个列表,要求列表中的数据为相同类型数据
如果obj传入一个正数,则表示在共享内存中开辟一个 多大的空间,空间中可以存放的数值类型 由ctype确定
返回值:返回一个可迭代对象通过for循环取值,可以进行修改

rom multiprocessing import Value,Process
import time 
import random 

def deposite(money):
    for i in range(100):
        time.sleep(0.03)
        money.value += random.randint(1,200) 

def withdraw(money):
    for i in range(100):
        time.sleep(0.02)
        money.value -= random.randint(1,150) 

money = Value('i',2000)
d = Process(target = deposite,args = (money,))
w = Process(target = withdraw,args = (money,))
d.start()
w.start()
d.join()
w.join()
print(money.value)

4、信号
kill -l 查看系统信号
kill -signame PID 给进程号PID的进程发送signame信号

信号 : 信号名称 含义 默认处理方法

名称 : 系统定义
含义 : 系统定义
处理方式 : 采用默认方式处理 (系统定义 终止 暂停 忽略
忽略信号(当信号没发生过)
采用自定义的方式处理

如何发送信号:
os.kill(pid,sig)
功能 : 向一个进程发送一个信号
参数 : pid :要发送进程的PID号
sig :要发送的信号

signal.alarm(sec)
功能:给自己发送一个时钟信号 (SIGALRM)
参数: sec : 秒数 表示在相应的秒数后发送时钟信号

  • 信号是一种异步的进程间通信方式
  • alarm 函数在一个进程中如果使用多次,则后面的时钟时间会覆盖前面的时间

信号的处理:

signal.pause()
阻塞等待一个信号的发生

signal.signal(signum,handler)
功能 : 处理信号
参数 : signum : 表示可以处理的信号
handler : 信号的处理方法
默认处理方式 : SIG_DFL
忽略信号 : SIG_IGN
自定义的方式 : function

  • signal函数也是一个异步处理信号函数

  • SIGSTOP 和 SIGKILL不能被signal函数处理
    僵尸进程的信号处理方案 父进程中

      signal(SIGCHLD,SIG_IGN)
      from signal import * 
      import os,time 
      #信号处理函数,有固定参数格式
      def handler(sig,frame):
          if sig == SIGALRM:
              print("收到了时钟信号")
          elif sig == SIGINT:
              print("收到了SIGINE就不结束")
      
      alarm(7)
      
      #通过函数 处理信号
      signal(SIGALRM,handler)
      signal(SIGINT,handler)
      
      while True:
          print("waiting for signal")
          time.sleep(2)
    

5、套接字
使用本地套接字实现进程间通信

发送
from socket import * 
from time import sleep
address = './sockfile'
s = socket(AF_UNIX,SOCK_STREAM)

try:
    s.connect(address)
except error as e:
    print(e)

try:
    message = b"This is a unix message"
    s.send(message)
    # sleep(20)
    data = s.recv(1024).decode()
    print('recv:',data)
except error as e:
    print(e)
finally:
    s.close()

接收
from socket import * 
import os 

#设置通信的套接字文件
address = './sockfile'

try:
    os.unlink(address)  #删除这个目录下的这个文件
except OSError:
    if os.path.exists(address): #判断文件是否删除成功
        raise

s = socket(AF_UNIX,SOCK_STREAM)
s.bind(address) #绑定本地套接字的文件
s.listen(5)

while True:
    conn,addr = s.accept()
    print("connect from",addr) #addr是空子串
    while True:
        data = conn.recv(1024).decode()
        if not data:
            break
        print("receive:",data)
        conn.send(b"receive your message")
    conn.close()
s.close()
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值