调用包含多个管道的命令到Popen
的正确方法是什么,以便可以读取其输出?我试过了:
Popen(shlex.split("mycmd arg1 | mysecondcmd - | thirdcmd -", stdout=PIPE)")
但我不相信shlex.split
就在这里。什么是正确的语法?
答案 0 :(得分:6)
您有几个选择 - 您可以传递shell=True
:
Popen('command1 | command2 | command3',shell=True)
或者,您可以将其分解成一堆Popen
次呼叫,将他们的标准输出连接到下一个Popen的标准输出,如documentation中所示。
答案 1 :(得分:2)
使用sh module,管道成为功能组合:
import sh
output = sh.thirdcmd(sh.mysecondcmd(sh.mycmd("arg1")))
如果您想在没有shell = True
的子流程中执行此操作,则会显示example in the docs,其中显示了如何使用subprocess.Popen
编写shell管道。请注意,您应该关闭proc.stdout
以便正确接收SIGPIPE
:
import subprocess
proc1 = subprocess.Popen(shlex.split('mycmd arg1'), stdout = subprocess.PIPE)
proc2 = subprocess.Popen(shlex.split('mysecondcmd'), stdin = proc1.PIPE,
stdout = subprocess.PIPE)
proc3 = subprocess.Popen(shlex.split('thirdcmd'), stdin = proc2.PIPE,
stdout = subprocess.PIPE)
# Allow proc1 to receive a SIGPIPE if proc2 exits.
proc1.stdout.close()
# Allow proc2 to receive a SIGPIPE if proc3 exits.
proc2.stdout.close()
out, err = proc3.communicate()
这可能看起来比使用shell = True
要多得多。您可能希望避免shell = True
的原因是因为it can be a security risk(向下翻到“警告”框),尤其是在您运行由(可能是恶意的)用户提供的命令时。