【问题标题】:Opening named pipe in one module, reading in the other在一个模块中打开命名管道,在另一个模块中读取
【发布时间】:2017-09-12 14:42:33
【问题描述】:

我很想为我的一个项目找出一些东西,但在一个问题上挂了:

我正在使用 FIFO 操作将“信号”(简单 T/F)从一个模块发送到另一个模块。一个模块打开 FIFO 进行写入,另一个模块打开 FIFO 进行读取。这里的目标是让读取模块在写入模块收到命令后立即读取和显示。写入模块打开了FIFO,但是读取模块好像没有这样做。

我正在尝试做的事情是否可能?我试图在 _threads 中旋转这两个操作,以保持每个模块中的多个进程。请注意,这两个模块都在我为简洁起见未包括在内的类中(解释“自我”)。

原发送模块

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))

更新发送模块

我意识到我不想将我扔给它的数据连续写入 FIFO,所以我删除了 while() 语句。现在看来,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()

接收模块

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'")

编辑

运行 Ubuntu 17.04。该项目是为 Python 3.5 解释器编写的。

【问题讨论】:

  • 操作系统、平台信息?
  • 我会发布编辑
  • 当您运行发送模块时,会显示哪些打印语句?你确定你正在给先进先出写信吗?
  • 我很确定你应该在写完之后fifo.flush()。见stackoverflow.com/questions/7048095/…

标签: python python-3.x ipc fifo mkfifo


【解决方案1】:

这里是使用Python 3.5.2编写的简单发送和获取sn-ps。
注释掉 fifo.flush() 行并查看行为差异。
使用flush,获取代码与发送代码一起运行。
没有它,get 代码在 fifo 关闭之前不会做出反应

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

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()

【讨论】:

    【解决方案2】:

    除了发送模块需要'w' 选项外,您还可能遇到发送或接收器未连接的问题。为了让另一个进程使用 fifo,发送方和接收方都必须打开 fifo 句柄。

    在 fifo 上查看 linux documentation。如果接收器没有在监听,你会得到一个 SIGPIPE,它通常会终止一个进程,但在 python 的情况下,它会等到接收器连接。

    如果您的发送者已死,而侦听器仍处于活动状态,则它会收到 EOF 并停止读取。

    【讨论】:

    • 有趣。接下来我会试试这个 - 感谢您继续提供帮助。你们帮助我学到了很多东西
    【解决方案3】:

    我有点惊讶代码没有引发异常。在您的编写器中,您执行常规的open(FILO),而不指定mode 参数。根据the documentationmode 默认为r(只读),所以我希望fifo.write(signal) 引发IOError。异常是否在某处被捕获?

    无论哪种方式,您都应该在写入端添加mode="w",以打开FIFO进行写入。

    【讨论】:

    • 这很好。让我看看结果如何。感谢您的洞察力
    • 暗示这是在单独的线程上运行的,这可以解释为什么它会崩溃而没有引发 visible 错误。
    • 我通过 'w''r' 选项运行了你上面的代码,它似乎工作。
    • @MadPhysicist 它正在一个单独的线程上运行。我对这两个概念(IPC、线程)的经验都很少,但是我使用 _thread 模块来保持一个进程在每个应用程序中运行,同时该 IPC 进程正在尝试完成其工作
    猜你喜欢
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    • 2011-04-15
    • 2022-01-08
    • 2020-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多