澄清一些要点:
正如 jro所提到的那样,正确的方法是使用subprocess.communicate
。
然而,当使用subprocess.communicate
并使用input
喂养stdin
时,您需要根据文档使用stdin=subprocess.PIPE
初始化子进程。
请注意,如果要向进程的stdin发送数据,则需要使用stdin=PIPE创建Popen对象。同样,要在结果元组中得到除 None 以外的任何东西,还需要给出stdout=PIPE和/或stderr=PIPE。
此外,qed在评论中提到,对于Python 3.4,您需要对字符串进行编码,这意味着您需要传递字节而不是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。这里使用echo的目的是将CATCH\nme
数据提供给grep。因此我们可以将数据作为变量使用Python subprocess链中的stdin传递给grep,并将stdout作为PIPE传递给wc
进程的stdin(同时去掉额外的换行符):
import subprocess
what_to_catch = 'catch'
what_to_feed = 'CATCH\nme'
p1 = subprocess.Popen(['grep', '-i', what_to_catch], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p1_out = p1.communicate(input=what_to_feed.encode())[0]
p1_out = p1_out.decode().strip().encode()
p2 = subprocess.Popen(['wc', '-m'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output = p2.communicate(input=p1_out)[0].decode().strip()
这与此处的回答有所不同,在Python中直接将两个进程连接而没有直接添加数据。
希望能对某人有所帮助。
subprocess.run
的input
; 例如,subprocess.run(['cat'], input='foobar'.encode('utf-8'))
。 - anishpatel