Python 命名管道

最近一个做一个项目,需要多个进程交互。同时,这几个进程需要各自独立启动,并无父子关系,评估后决定使用命名管道方式进行进程通信。为保证消息完整性以及并发安全,使用文件锁保证读写的原子性。代码如下:

import multiprocessing
import os
import traceback
import time
import json
import sys
import fcntl

class Pipe:
    def __init__(self, pipe_name):
        file_path = "/tmp/"
        try:
            self.fifo_path = "{}{}.pipe".format(file_path, pipe_name)
            os.mkfifo(self.fifo_path)
        except Exception:
            print(traceback.format_exc())
        self.block_file = "/tmp/block_{}.file".format(pipe_name)
        if not os.path.exists(self.block_file):
            f = open(self.block_file, "w")
            f.close()
        self.fp_block = open(self.block_file, "w")

    def __lock(self, flag=fcntl.LOCK_EX | fcntl.LOCK_NB):
        fcntl.flock(self.fp_block.fileno(), flag)

    def __unlock(self):
        fcntl.flock(self.fp_block.fileno(), fcntl.LOCK_UN)

    def send(self, msg):
        try:
            self.__lock()
            f = os.open(self.fifo_path, os.O_RDWR | os.O_NONBLOCK)
            os.write(f, "{};".format(json.dumps(msg)).encode("utf-8"))
        except Exception:
            print(traceback.format_exc())
            return False
        finally:
            self.__unlock()
        return True

    def receive(self):
        msg_str = ""
        try:
            self.__lock()
            f = os.open(self.fifo_path, os.O_RDWR | os.O_NONBLOCK)
            while True:
                s = os.read(f, 1).decode("utf-8")
                if s != ";":
                    msg_str += s
                else:
                    break
        except Exception:
            print(traceback.format_exc())
            return ""
        finally:
            self.__unlock()
        return msg_str


if __name__ == '__main__':
    pipe_name = "test.pipe"
    pid = os.fork()
    if pid:
        pipe = Pipe(pipe_name)
        pipe.send({"code": "A00000", "data": "xxx"})
        pipe.send({"code": "A00000", "data": "yyy"})
        time.sleep(10)
        print("send end")
    else:
        pipe = Pipe(pipe_name)
        time.sleep(1)
        s = pipe.receive()
        print("receive1 = {}".format(s))
        s = pipe.receive()
        print("receive2 = {}".format(s))
        pass
    sys.exit(0)

 

你可能感兴趣的:(Python 命名管道)