在python

时间:2017-05-25 01:19:04

标签: python unix named-pipes

关于堆栈溢出的这些主题有相当多的材料,没有一个完全回答我的问题(见下文),但它帮助我找到了可能的解决方案。然而,我想知道这些解决方案有多强大(即,我错过了一些明显的缺陷......)以及是否有更好/更清洁/更pythonic的方法来解决这个问题。我用于此的堆栈溢出线程如下:

[1] Python read named PIPE

[2] unix pipe multiple writers

[3] How do I properly write to FIFOs in Python?

我的问题如下:我有一个python可执行文件,它将在一台机器上永久运行。它需要从其他进程读取一些消息(例如,管理员SSH进入机器必须能够向其发送消息;可能其他批处理可执行文件也可以向其发送消息)。每条消息都是一行文本(以unix' \ n'字符结尾)。我想使用unix命名管道来实现它:可执行文件将在启动时创建命名管道并打开它来监听消息。然后发送消息只是在该命名管道上写一行。

约束:我不期望大量的消息,但我确实希望并发消息写入行为合理。我不希望消息被忽略只是因为管理员不幸的是在另一个人或程序发送另一条消息的同时发送消息。

为此推荐的一般解决方案(特别是参见上面的[1])似乎是某种双循环:

fifo = '/path/to/namedpipe'
os.mkfifo(fifo)
def read_fifo(fifo):
    while True:
        with open(fifo) as fh:
            for line in fh:
                print "Read command: " + line

这似乎运作良好但至少有三种我能想到的竞争条件:

(a)内在' for'当所有编写器关闭其文件句柄并且已经迭代完所有写入的数据时,循环终止。如果此时编写者进入并写入一条消息(即:再次打开管道,写入,关闭管道),之后管道已关闭并由外部管道再次打开。而'读取器的循环,然后读取器中外部while循环的下一次迭代将不会读取此最后一个写入器写入的消息。它丢失了。

(b)内心之后&#39;循环终止,如果编写器打开管道进行写入但停在那里,则管道由读取器关闭(因为我们退出&#39; with&#39;块)然后编写器尝试向管道写入内容< em>在之前,读者再次打开它,这位作家将获得一个&#34; Broken Pipe&#34;错误。

(c)在某些情况下,至少看起来像内在的&#39;循环只会在所有编写器关闭文件句柄时开始处理元素(某些源,如[1],甚至建议调用File.read(),保证始终以这种方式运行)。这意味着如果总是一个活动的编写器,读者将无法处理任何内容。

(c)并不会让我感到烦恼,但(a)和(b)是一个问题。

我尝试了什么:

问题似乎是读者必须反复关闭/打开管道,这会导致错误或消息被丢弃。我试图通过在阅读器中只打开一次管道来摆脱双循环,然后使用readline()方法连续循环,从管道读取。主要问题是当所有编写器关闭其句柄时,readline()不会等待输入(它会立即返回一个空字符串)。因此,为了避免非常快速地循环并使用大量CPU,我只有两个选项:(1)睡眠,或(2)打开管道进行内部写入...读者。

(1)看起来像这样:

def read_fifo(fifo):
    with open(fifo) as fh:
        line = fh.readline()
        while True:
            time.sleep(1)
            # We don't want to print all the empty lines returned by readline() when no writer have the pipe opened
            if line:
                print "Read command: " + line
            line = fh.readline()

(2)看起来像这样:

def read_fifo(fifo):
    with open(fifo) as fh:
        dummy_file_handle = open(fifo, 'w')
        line = fh.readline()
        while True:
            print "Read command: " + line
            # Here, readline() should always block since there is always at least one process holding an open write handle to the pipe
            line = fh.readline()
        dummy_file_handle.close()

上面的两个选项看起来有点hacky,而我想要做的事情看起来就像命名管道的基本用法。你们认为这会正常吗?我错过了什么,这是一种更简单,更好的方法吗?

提前感谢您的帮助!

0 个答案:

没有答案