【发布时间】:2017-04-17 12:59:29
【问题描述】:
我正在为一个可选择接受来自 STDIN 的输入的程序编写一个包装脚本。我的脚本需要处理文件的每一行,但它还需要将 STDIN 转发到它正在包装的程序。在极简形式中,它看起来像这样:
import subprocess
import sys
for line in sys.stdin:
# Do something with each line
pass
subprocess.call(['cat'])
请注意,我实际上并不是要包装 cat,它只是作为示例来演示 STDIN 是否被正确转发。
在上面的例子中,如果我注释掉for循环,它就可以正常工作。但是,如果我使用 for 循环运行它,则不会转发任何内容,因为我已经读到了 STDIN 的末尾。我不能 seek(0) 到文件的开头,因为你不能在流上搜索。
一种可能的解决方案是将整个文件读入内存:
import subprocess
import sys
lines = sys.stdin.readlines()
for line in lines:
# Do something with each line
pass
p = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
p.communicate(''.join(lines))
有效,但内存效率不高。谁能想到更好的解决方案?也许是一种拆分或复制流的方法?
其他约束:
- 子进程只能调用一次。所以我不能一次读取一行,处理它,然后转发给子进程。
- 该解决方案必须在 Python 2.6 中运行
【问题讨论】:
-
如果我理解正确的话,你想基本上将数据从
stdin转发到子进程的stdin? -
是的,但如果我只想将
stdin转发到子进程,那么我只需要subprocess.call(['cat'])。我想转发stdin并且能够阅读和处理它。 -
很难判断我是否正确理解了您的问题。从:
python -c $'import subprocess;\nimport sys;\np = subprocess.Popen(["cat", "-n"], stdin=subprocess.PIPE);\nfor line in iter(sys.stdin.readline,""): p.stdin.write(line)'开始(把它放在一个普通的 .py 文件中,我只是把它放在一行上,这样我就可以在这个评论中得到它)。然后在p.stdin.write(line)之前插入do_something_else_with(line)。由于某种原因,您的约束 #1 听起来对您不起作用,但我不明白为什么不这样做。你能澄清一下吗?
标签: python stream subprocess stdin