未在 Tornado 中接收所有命名管道输出

Posted

技术标签:

【中文标题】未在 Tornado 中接收所有命名管道输出【英文标题】:Not receiving all named pipe output in Tornado 【发布时间】:2015-04-20 15:00:45 【问题描述】:

我正在使用 Tornado 运行一个小型 python 程序,它收集由另一个程序编写的多个 linux 命名管道 (FIFO) 输出。不幸的是,由于某种原因,并没有收到管道的所有输出。

我像这样添加管道:

for pipe in pipe_files:
    pipe_file = open(pipe, 'r')
    try:
        pipe_stream = Pipeiostream(pipe_file.fileno())
        self.output_streams.append(pipe_stream)
    except IOError:
        logging.warn("Can't open pipe %s", pipe)
        continue
    self.read_lines(pipe_stream, self.new_output)

Read lines 像这样注册一个回调:

def read_lines(self, stream, callback):
    """
    Read lines forever from the given stream, calling the callback on each line.

    :param stream: a tornado.BaseIOStream
    :param callback: callback method to be called for each line.
    """
    def wrapper(line):
        if not self.output_streams:
            # Output streams have been removed, no need to continue.
            return

        callback(line.strip())
        # Reregister the callback, if the stream hasn't closed yet.
        if not stream.closed():
            stream.read_until(os.linesep, callback=wrapper)
    stream.read_until(os.linesep, callback=wrapper)

我最终使用 tornado 的子进程运行程序(也以相同的方式捕获其 stdout/err)并在子进程结束时退出。

我没有收到所有预期的输出(例如,我将在程序中打印 10000 行,但在 python 程序中只收到 ~7000 行)。当我简单地使用“cat”来获取fifo输出时,我可以看到它。

我确保程序正确刷新输出。我尝试在程序中永远休眠以让 Tornado 有时间获得输出,但结果相同。

有什么想法吗?

【问题讨论】:

我在我的 C 程序中添加了 10 秒的睡眠和刷新,但仍然没有通过龙卷风中的管道接收到数据(虽然我确实看到了标准输出)。 【参考方案1】:

stream.closed() 可能在缓冲区中仍有数据时变为真。为确保您已阅读所有内容,请使用 set_close_callback() 并阅读直到运行该回调,或使用协程样式接口并阅读直到收到 StreamClosedError。

一般情况下,写的时候应该用stream.closed(),这样你就不要尝试写一个已经不在的客户端了,但是读close回调更合适。

【讨论】:

等待 StreamClosedError 似乎不起作用(仍在使用回调)。我得到了错误,但仍然没有写入数据。【参考方案2】:

通过在我的 C 程序中更改管道的开口来解决问题:

open(fifo_path, O_WRONLY | O_NONBLOCK);

收件人:

open(fifo_path, O_RDWR);

见thesequestions。

【讨论】:

以上是关于未在 Tornado 中接收所有命名管道输出的主要内容,如果未能解决你的问题,请参考以下文章

通过命名管道访问单例会创建第二个单例。未在主机端触发的事件

命名管道吞下 Linux 命令输出的第一个字段

linux进程间的通信(C): 消息队列

如何从多个命名管道接收消息?

检测命名管道与 I/O 完成断开连接

从命名管道到提交日志的 Julia 输出