简体   繁体   English

在一个模块中打开命名管道,在另一个模块中读取

[英]Opening named pipe in one module, reading in the other

I'm hot on the trail of figuring something out for one of my projects, but hung up on one issue: 我正忙着为我的一个项目找出一些东西,但我还挂了一个问题:

I'm using a FIFO operation to send a 'signal' (simple T/F) from one module to another. 我正在使用FIFO操作从一个模块向另一个模块发送“信号”(简单T / F)。 One module opens the FIFO to write to it, and the other opens the FIFO to read from it. 一个模块打开FIFO以写入它,另一个模块打开FIFO以从中读取。 The goal here is to have the reading module immediately read and display as soon as the writing module receives the command to do so. 这里的目标是在写入模块接收到命令时立即读取并显示读取模块。 The writing module opens the FIFO, but the reading module doesn't seem to do so. 写入模块打开FIFO,但读取模块似乎不这样做。

Is what I'm trying to do even possible? 我正在努力做甚么可能吗? I'm trying to spin both operations in _threads in order to keep multiple processes going in each module. 我试图在_threads中旋转两个操作,以便在每个模块中保持多个进程。 Note both modules are in classes that I didn't include for the sake of brevity (explaining 'self'). 请注意,为了简洁起见,这两个模块都在我没有包含的类中(解释'self')。

original sending module 原始发送模块

def pipe_relay(self):
    FIFO = 'pipe_relay'
    thread_num = num

    try:
        os.mkfifo(FIFO)
    except OSError as oe:
        if oe.errno != errno.EEXIST:
            raise

    while self.relay_switch:
        print("Opening FIFO...")
        with open(FIFO) as fifo:
            print("FIFO opened")
            while self.relay_switch:
                data = fifo.write(signal)
                if len(data) == 0:
                    print("Writer is closed")
                    break
                print('Write: "{0}"'.format(data))

updated sending module 更新发送模块

I realized that I didn't want to be writing to the FIFO continuously with the data I threw at it, so I removed the while() statement. 我意识到我不想用我投入的数据连续写入FIFO,所以我删除了while()语句。 Now, it doesn't seem as though the FIFO will open at all... 现在,似乎FIFO根本不会打开......


def pipe_relay(self, num, signal):
    FIFO = 'pipe_relay'
    thread_num = num

    try:
        os.mkfifo(FIFO)
    except OSError as oe:
        if oe.errno != errno.EEXIST:
            raise

    print("Opening FIFO...")

    # does not proceed past this point

    with open(FIFO, mode = 'w') as fifo:
        print("FIFO opened")
        data = fifo.write(signal)
        if len(data) == 0:
            print("Writer is closed")
        print('Write: "{0}"'.format(data))
        fifo.close()

receiving module 接收模块

def pipe_receive(self):
    FIFO = 'pipe_relay'

    try:
        os.mkfifo(FIFO)
    except OSError as oe:
        if oe.errno != errno.EEXIST:
            raise   

    # module proceeds to here, but no further

    with open(FIFO) as fifo:
        print("FIFO opened (receiver)")
        while True:
            data = fifo.read()
            if len(data) == 0:
                print("Writer is closed")
                break
            print('Read signal: "{0}"'.format(data))
            self.DISPLAY['text'] = data
    print("this is in 'pipe_receieve'")

EDIT 编辑

Running Ubuntu 17.04. 运行Ubuntu 17.04。 The project is written for the Python 3.5 interpreter. 该项目是为Python 3.5解释器编写的。

Here are simple send and get snippets written using Python 3.5.2 . 以下是使用Python 3.5.2编写的简单send和get片段。
Comment out the fifo.flush() line and see the difference in behaviour. 注释掉fifo.flush()行并查看行为上的差异。
With flush the get code operates in tandem with the send code. 使用flush ,get代码与发送代码一起运行。
Without it, the get code does not react until the fifo is closed 没有它,get代码在fifo关闭之前不会做出反应

send.py send.py

import sys, os, time

path = "/tmp/my.fifo"
try:
    os.mkfifo(path)
except:
    pass
try:
    fifo = open(path, "w")
except Exception as e:
    print (e)
    sys.exit()
x = 0
while x < 5:
    fifo.write(str(x))
    fifo.flush()
    print ("Sending:", str(x))
    x+=1
    time.sleep(3)
print ("Closing")
fifo.close()
try:
    os.unlink(fifo)
except:
    pass

get.py get.py

import os, sys

path = "/tmp/my.fifo"
try:
    fifo = open(path, "r")
except Exception as e:
    print (e)
    sys.exit()
while True:
    r = fifo.read(1)
    if len(r) != 1:
        print ("Sender Terminated")
        break
    print ("Received:", r)
fifo.close()

I'm a bit surprised that the code doesn't raise an exception. 我有点惊讶的是代码没有引发异常。 In your writer, you do a regular open(FILO) , without specifying the mode parameter. 在您的编写器中,您执行常规open(FILO) ,而不指定mode参数。 According to the documentation , mode defaults to r (read-only), so I would expect the fifo.write(signal) to raise an IOError . 根据文档mode默认为r (只读),所以我希望fifo.write(signal) IOError Are Exceptions being caught somewhere? 异常是否被某处抓获?

Either way, you should add a mode="w" to the writer-side to open the FIFO for writing. 无论哪种方式,您都应该向编写器端添加mode="w"以打开FIFO进行写入。

In addition to requiring the 'w' option to the sending module, you may also be having issues with either the sending or receiver not being connected. 除了要求发送模块的'w'选项外,您可能还遇到了发送或接收器未连接的问题。 In order for another process to make use of a fifo, both the sender and receiver must have the fifo handle open. 为了使另一个进程能够使用fifo,发送方和接收方都必须打开fifo句柄。

See the linux documentation on a fifo. 请参阅fifo上的linux 文档 If the receiver is not listening, you get a SIGPIPE which typically will terminate a process but in python's case it will wait until a receiver is connected. 如果接收器没有监听,你会得到一个SIGPIPE,通常会终止一个进程,但在python的情况下,它将等到接收器连接。

If your sender is dead and the listener is still active it received an EOF and stops reading. 如果您的发件人已经死亡且收听者仍处于活动状态,则会收到EOF并停止阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM