我有一条处理链:
以前的一种方法是
cat input | preprocess.sh | transform.py | postprocess.sh
这适用于处理批量输入数据。
但是,我现在发现自己需要在Python中将其实现为服务器功能 - 我需要能够接受单个数据项,运行管道并快速将其吐出。
我只是在Python中调用的中心步骤,所以这是最简单的部分。后处理也相对容易。
问题在于:预处理代码由4个不同的脚本组成,每个脚本将数据输出到下一个脚本,其中两个脚本需要从磁盘加载模型文件才能工作。这种加载速度相对较慢,对我的执行时间来说也很糟糕。因此我认为我需要以某种方式将它们保存在内存中,写入stdin
并读取输出。
但是,我发现对于我的链中的每个链接,我都无法写入stdin
并在不关闭stdout
的情况下阅读stdin
,这会使该方法无效然后我必须重新打开该过程并再次加载模型。
请注意,这对我的脚本来说不是问题,就像链中的每个链接一样
cat input_data | preprocessing_script_i.sh
返回Bash中的内容。
以下是我迄今为止尝试过的事情:
stdin
和flush
- 在readline上无限期等待process.communicate
- 杀死了这个过程,因此无从谈起。pty
句柄 - 挂在阅读线上stdout
时读取stdin
bufsize
subprocess
有没有办法从Python做到这一点?这是否有可能,因为我开始怀疑这一点?可以重新实现这个管道(不触及元素,因为对我的用例来说不太可行)在另一种语言中解决这个问题吗?
答案 0 :(得分:1)
最简单的可能是来自同一文件系统的mv
个文件(因为重命名对文件操作是原子的,而cp
不是原子的)到“输入目录”。 shell无限循环,等待新文件mv
到“工作目录”处理它,并mv
在“完成目录”或“错误目录”中。
答案 1 :(得分:1)
您可以避免使用FIFO的stdin / stdout相关问题
os.mkfifo("/tmp/fifo")
然后,您可以将Python中的这个用作文件,用于从不同进程读取和写入目的,您甚至可以查看读者中的fifo(Python: Check if named pipe has data)以检查是否有东西要在那里阅读。
如果没有这样的帮助,另一种方法是用消息传递平台取代进程间通信。 ZeroMQ(zmq)很容易实现,不需要任何服务器组件,然后你就可以摆脱链接的输入和输出。您只需从一个进程发布消息并从另一个进程读取它们。数据传输但使用线程读取器,您不会遇到阻塞IO。
答案 2 :(得分:0)
对不起,提出的想法很棒,这可能不会帮助很多人,但这就是我解决问题的方法。
事实证明,perl
有一个-b
标志,用于在线缓冲模式下打印。一旦我将其插入处理管道的perl -b script.perl
部分,事情就开始顺利进行,简单的process.write()
后跟.flush()
足以获得输出。
我会尝试更改问题标签和标题,以更好地适应实际问题。