如何在子进程中使用猫和管道的混合物

时间:2015-01-20 20:30:34

标签: python-3.x pipe subprocess cat

我正在尝试捕获文件的内容并将其传递到第二个python脚本的stdin中,然后将其中的stdout放入另一个文件中。

在命令行上,它看起来像这样:

cat input_file | python3 ~/Desktop/python_script.py > output_file

我在阅读了很多帖子之后试图这样做

file_input = subprocess.Popen(('cat', input_file), stdout=subprocess.PIPE)
file_output = subprocess.check_output(('python3', '~/Desktop/mdparser.py'), stdin=file_input.stdout, stdout=subprocess.PIPE)
subprocess.check_output('>','output_file',stdin = file_output.stdout)

但是我在第二行收到以下错误:

File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 598, in check_output
    raise ValueError('stdout argument not allowed, it will be overridden.')
ValueError: stdout argument not allowed, it will be overridden.

1 个答案:

答案 0 :(得分:1)

这应该只是一个电话,而不是三个。

exit_status = subprocess.call(
  ['python3', os.path.expanduser('~/Desktop/mdparser.py')],
  stdin=open('input_file', 'r'), stdout=open('output_file', 'w'))

Tilde扩展(~/foo)由shell处理;如果你没有shell,就像这里一样,你需要自己明确地做 - 这就是os.path.expanduser所做的。

check_output()被重定向时,你不能使用stdout,无论是对于不同的进程还是文件 - 这就是抛出异常的原因,因为Python解释器不能同时读取将内容转换为变量并将其直接连接到不同进程的管道中。这就是消息意味着“将被覆盖” - 当你使用check_output()时,你告诉Python解释器从管道本身读取输出,但是当你将输出配置为转到其他进程或文件。

相反,将输出直接指向文件,然后打开文件并在完成后阅读。


不使用cat的另一个原因是它所做的只是增加低效率并限制操作。当你跑:

foo <input.txt >output.txt

......或者,如果您更喜欢表格......

<input.txt foo >output.txt

... foo程序直接在input.txt上获取文件句柄,另一个直接在output.txt上获取文件句柄。当你不使用cat时,这些文件句柄是真正的交易 - 它可以在文件中寻找,这意味着如果你的程序必须返回并查看先前的内容,它可以告诉文件句柄返回并寻找不同的部分。相比之下,如果你运行cat input.txt | foo,那么foo必须存储它在内存中读取的所有内容,如果它正在执行的操作需要多次传递。

使用cat只是开销 - 这是一个额外的程序,它从输入文件中读取并写入管道的一半,毕竟,这意味着它在管道和上下文之间进行额外的IO切换到内核和从内核切换。除非你需要,否则不要使用它 - 例如,如果你将多个文件连接成一个流(这是cat的目的,因此它的名字)