设为首页 加入收藏

TOP

python多进程通信实例分析(一)
2019-09-04 01:02:18 】 浏览:49
Tags:python 进程 通信 实例分析

操作系统会为每一个创建的进程分配一个独立的地址空间,不同进程的地址空间是完全隔离的,因此如果不加其他的措施,他们完全感觉不到彼此的存在。那么进程之间怎么进行通信?他们之间的关联是怎样的?实现原理是什么?本文就来借助Python简单的聊一下进程之间的通信?还是那句话,原理是相同的,希望能透过具体的例子来体会一下本质的东西。

 下面尽量以简单的方式介绍一下每一类通信方式,具体的细节可以参照文档使用;

1. 管道

先来看一下最简单、古老的一种IPC:管道。通常指的是无名管道,本质上可以看做一种文件,只存在于内存当中,不会存盘。不同进程通过系统提供的接口来向管道中读取或者写入数据。

也就是说我们通过这样一个中间介质为进程提供交流的方式。无名管道的局限在于一般只用于有直接关联关系的父子进程。下面通过一个简单的例子来看一下其用法。

from multiprocessing import Process, Pipe

def pstart(pname, conn):
    conn.send("Data@subprocess")
    print(conn.recv())          # Data@parentprocess

if __name__ == '__main__':
    conn1, conn2 = Pipe(True)
    sub_proc = Process(target=pstart, args=('subprocess', conn2,))
    sub_proc.start()
    print (conn1.recv())        # Data@subprocess
    conn1.send("Data@parentprocess")
    sub_proc.join()

管道通信三步曲:

  1. 创建Pipe,得到两个connection对象conn1和conn2;
  2. 父进程持有conn1,将conn2传递给子进程;
  3. 父子进程通过对持有的connection对象进行send和recv操作以进行数据传递和接受;

上面我们创建的是全双工管道,也可以创建半双工管道,具体使用可以参照官网描述:

Returns a pair (conn1, conn2) of Connection objects representing the ends of a pipe.

If duplex is True (the default) then the pipe is bidirectional. If duplex is False then the pipe is unidirectional: conn1 can only be used for receiving messages and conn2 can only be used for sending messages.

2. 具名管道(FIFO)

上面介绍的管道主要用于有直接关系的进程,局限性比较大。下面来看一下可以在任意进程间进行通信的具名管道。

由于window平台上os模块没有mkfifo属性,因此这个例子只能在linux上运行(测试环境 CentOS 7, Python 2.7.5):

#!/usr/bin/python
import os, time
from multiprocessing import Process

input_pipe = "./pipe.in"
output_pipe = "./pipe.out"

def consumer():
    if os.path.exists(input_pipe):
        os.remove(input_pipe)
    if os.path.exists(output_pipe):
        os.remove(output_pipe)

    os.mkfifo(output_pipe)
    os.mkfifo(input_pipe)
    in1 = os.open(input_pipe, os.O_RDONLY)        # read from pipe.in
    out1 = os.open(output_pipe, os.O_SYNC | os.O_CREAT | os.O_RDWR)
    while True:
        read_data = os.read(in1, 1024)
        print("received data from pipe.in: %s @consumer" % read_data)
        if len(read_data) == 0:
            time.sleep(1)
            continue

        if "exit" in read_data:
            break
        os.write(out1, read_data)
    os.close(in1)
    os.close(out1)

def producer():
    in2 = None
    out2 = os.open(input_pipe, os.O_SYNC | os.O_CREAT | os.O_RDWR)

    for i in range(1, 4):
        msg = "msg " + str(i)
        len_send = os.write(out2, msg)
        print("------product msg: %s by producer------" % msg)
        if in2 is None:
            in2 = os.open(output_pipe, os.O_RDONLY)        # read from pipe.out
        data = os.read(in2, 1024)
        if len(data) == 0:
            break
        print("received data from pipe.out: %s @producer" % data)
        time.sleep(1)

    os.write(out2, 'exit')
    os.close(in2)
    os.close(out2)

if __name__ == '__main__':
    pconsumer = Process(target=consumer, args=())
    pproducer = Process(target=producer, args=())
    pconsumer.start()
    time.sleep(0.5)
    pproducer.start()
    pconsumer.join()
    pproducer.join()

运行流程如下:

 每一轮的过程如下:

  1. producer进程往pipe.in文件中写入消息数据;
  2. consumer进程从pipe.in文件中读入消息数据;
  3. consumer进程往pipe.out文件中写入回执消息数据;
  4. producer进程从pipe.out文件中读出回执消息数据;

结果如下:

[shijun@localhost python]$ python main.py
------product msg: msg 1 by producer------
received data from pipe.in: msg 1 @consumer
received data from pipe.out: msg 1 @producer
------product msg: msg 2 by producer------
receiv
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Mac os 下 python爬虫相关的库和.. 下一篇python中的lambda表达式

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目