代码之家  ›  专栏  ›  技术社区  ›  Dominik Stańczak

持久子进程管道-读取标准输出,不带

  •  0
  • Dominik Stańczak  · 技术社区  · 7 年前

    我有一个处理链,沿着以下路线:

    1. 通过几个步骤预处理数据,包括从单个Bash脚本中调用perl、Bash和python脚本,并通过管道连接这些脚本
    2. 用python转换数据(遗憾的是,我使用的程序没有在python 3上运行,所以我想我不得不运行2.7)
    3. 像预处理步骤一样对数据进行后处理

    这种方法以前的一种有效方法是

    cat input | preprocess.sh | transform.py | postprocess.sh
    

    这在处理成批输入数据时效果很好。

    然而,我现在发现自己需要在Python中将其实现为服务器功能—我需要能够接受单个数据项,运行管道并快速将其吐出。

    我刚才从Python内部调用的中心步骤,这是最简单的部分。后处理也相对容易。

    问题是:预处理代码由4个不同的脚本组成,每个脚本将数据输出到下一个脚本,其中两个脚本需要从磁盘加载模型文件才能工作。加载速度相对较慢,对我的执行时间造成了可怕的影响。因此,我认为我需要以某种方式记住他们,写信给他们 stdin s并读取输出。

    然而,我发现,对于链中的每一个链接,我都无法写信给 标准DIN 并读取 stdout 无需关闭 标准DIN ,这将使该方法变得无用,因为我将不得不重新打开进程并再次加载模型。

    请注意,对于链中的每个链接,这不是我的脚本的问题

    cat input_data | preprocessing_script_i.sh
    

    返回Bash中应该返回的内容。

    以下是我迄今为止尝试过的东西:

    • 只需写信给 标准DIN flush 它-在readline上无限期等待
    • process.communicate -终止进程,因此是不可能的。
    • 使用主控和从控 pty 句柄-挂起在readline上
    • 使用队列和线程读取 标准装置 写信给时 标准DIN 从主线程
    • 胡闹 bufsize 在呼叫中 subprocess

    有什么方法可以从Python实现这一点吗?我开始怀疑这有可能吗?用另一种语言重新实现这个管道(不涉及元素,因为这对我的用例不太可行)能为我解决这个问题吗?

    3 回复  |  直到 7 年前
        1
  •  1
  •   Nahuel Fouilleul    7 年前

    最简单的可能是 mv 来自同一文件系统的文件(因为重命名是原子覆盖文件操作,而 cp 是非原子的)到“输入目录”。shell无限循环并等待新文件 中压 到“工作目录”处理它,并 中压 它位于“完成目录”或“错误目录”中。

        2
  •  1
  •   Hannu    7 年前

    使用FIFO可以避免与stdin/stdout相关的问题

    os.mkfifo("/tmp/fifo")
    

    然后,您可以将Python中的该文件用作不同进程的读写文件,甚至可以查看fifo( Python: Check if named pipe has data )在读卡器中检查是否有需要阅读的内容。

    如果没有这样的帮助,另一种方法是用消息平台取代进程间通信。ZeroMQ(zmq)很容易实现,不需要任何服务器组件,然后就可以摆脱输入和输出的链接。您只需发布来自一个进程的消息,然后从另一个进程读取它们。数据可以传输,但通过线程读取器,您不会被阻塞IO所困扰。

        3
  •  0
  •   Dominik Stańczak    7 年前

    很抱歉,提出的想法很好,这可能不会在将来帮助很多人,但这就是我解决问题的方法。

    事实证明 perl 有一个 -b 行缓冲模式下打印的标志。一旦我把它插入 perl -b script.perl 作为处理流程的一部分,事情开始顺利进行 process.write() 然后 .flush() 足以获得输出。

    我将尝试更改问题标签和标题,以更好地适应实际问题。