我这两天一直在用python和Popen较量,所以我决定把我所有的疑惑都放在这里,希望所有的问题都能得到python专家的澄清。
最初我使用 Popen 执行命令并 grep 结果(作为一个使用管道的命令,类似于 xxx | grep yyy),使用 shell=False,如你可以想象,这不是很好。按照 this 中的指南进行操作发布后,我将代码更改为以下内容:
checkCmd = ["sudo", "pyrit", "-r", self.capFile, "analyze"]
checkExec = Popen(checkCmd, shell=False, stdout=PIPE, stderr=STDOUT)
grepExec = Popen(["grep", "good"], stdin=checkExec.stdout, stdout=PIPE)
output = grepExec.stdout.readline()
output = grepExec.communicate()[0]
但我意识到 checkExec 运行缓慢并且由于 Popen 是非阻塞的,grepExec 总是在 checkExec 显示任何结果之前执行,因此 grep 输出将始终为空白。如何将 grepExec 的执行推迟到 checkExec 完成?
在我的程序中的另一个 Popen 中,我试图在后面保持一个服务打开,所以我使用一个单独的线程来执行它。当所有任务完成后,我通知该线程退出,并显式调用 Popen.kill() 来停止服务。然而,我的系统以一个没有被收割的僵尸进程结束。不知道有没有什么好的方法可以在这个后台线程结束后清理所有东西?
Popen.communicate()[0] 和 Popen.stdout.readline() 有什么区别?我可以使用循环来继续读取它们的输出吗?
请您参考如下方法:
如果您这样做,您的示例将有效:
checkCmd = ["sudo", "pyrit", "-r", self.capFile, "analyze"]
checkExec = Popen(checkCmd, shell=False, stdout=PIPE, stderr=STDOUT)
grepExec = Popen(["grep", "good"], stdin=checkExec.stdout, stdout=PIPE)
for line in grepExec.stdout:
# do something with line
当你想给进程一些输入并同时读取进程的 stdout 和 stderr 上的所有输出时,你可以使用 communicate。这可能不是您想要的。 communicate 更适用于您想要启动应用程序、向其提供所需的所有输入并读取其输出的情况。
正如其他答案所指出的,您可以使用 shell=True 在对子进程的调用中创建管道,但我更喜欢的替代方法是利用 python 而不是设置管道做:
checkCmd = ["sudo", "pyrit", "-r", self.capFile, "analyze"]
checkExec = Popen(checkCmd, shell=False, stdout=PIPE, stderr=STDOUT)
for line in checkExec.stdout:
if line.find('good') != -1:
do something with the matched line here
