澄清几点:
由于jro有mentioned,正确的做法是使用subprocess.communicate。
然而,当使用subprocess.communicate 和input 提供stdin 时,您需要根据docs 使用stdin=subprocess.PIPE 启动子进程。
请注意,如果您想将数据发送到进程的标准输入,您需要使用标准输入=PIPE 创建 Popen 对象。同样,要在结果元组中获取 None 以外的任何内容,您也需要提供 stdout=PIPE 和/或 stderr=PIPE。
qed 在 cmets 中还提到,对于 Python 3.4,您需要对字符串进行编码,这意味着您需要将 Bytes 传递给 input 而不是 string。这并不完全正确。根据文档,如果流以文本模式打开,则输入应该是一个字符串(源是同一页)。
如果流以文本模式打开,则输入必须是字符串。否则,它必须是字节。
所以,如果流没有在文本模式下显式打开,那么下面的内容应该可以工作:
import subprocess
command = ['myapp', '--arg1', 'value_for_arg1']
p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = p.communicate(input='some data'.encode())[0]
我特意将上面的stderr 值保留为STDOUT 作为示例。
话虽如此,有时您可能想要另一个进程的输出,而不是从头开始构建它。假设您要运行 echo -n 'CATCH\nme' | grep -i catch | wc -m 的等价物。这通常应该返回 'CATCH' 中的数字字符加上一个换行符,结果为 6。这里的回显点是将CATCH\nme 数据提供给 grep。因此,我们可以将 Python 子进程链中的标准输入作为变量提供给 grep,然后将标准输出作为 PIPE 传递给wc 进程的标准输入(同时,去掉多余的换行符):
import subprocess
what_to_catch = 'catch'
what_to_feed = 'CATCH\nme'
# We create the first subprocess, note that we need stdin=PIPE and stdout=PIPE
p1 = subprocess.Popen(['grep', '-i', what_to_catch], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
# We immediately run the first subprocess and get the result
# Note that we encode the data, otherwise we'd get a TypeError
p1_out = p1.communicate(input=what_to_feed.encode())[0]
# Well the result includes an '\n' at the end,
# if we want to get rid of it in a VERY hacky way
p1_out = p1_out.decode().strip().encode()
# We create the second subprocess, note that we need stdin=PIPE
p2 = subprocess.Popen(['wc', '-m'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
# We run the second subprocess feeding it with the first subprocess' output.
# We decode the output to convert to a string
# We still have a '\n', so we strip that out
output = p2.communicate(input=p1_out)[0].decode().strip()
这与here 的响应有些不同,后者直接通过管道传输两个进程,而无需直接在 Python 中添加数据。
希望对某人有所帮助。