1

我已经在python中与Popen战斗了几天,所以我决定把我所有的疑问放在这里,希望所有这些都可以被python专家澄清。

最初,我使用 Popen 执行命令并 grep 结果(作为一个使用管道的命令,例如xxx | grep yyy),shell=False正如您可以想象的那样,这不太好用。按照这篇文章中的指南,我将代码更改为以下内容:

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完成?

  1. 在我程序的另一个 Popen 中,我试图在后面保持一个服务打开,所以我使用一个单独的线程来执行它。完成所有任务后,我通知该线程退出,并显式调用 Popen.kill() 停止服务。但是,我的系统最终会出现一个没有收割的僵尸进程。不知道有没有什么好办法可以在后台线程完成后清理掉所有的东西?

  2. Popen.communicate()[0] 和 Popen.stdout.readline() 有什么区别?我可以使用循环来继续读取它们的输出吗?

4

2 回答 2

4

如果您这样做,您的示例将起作用:

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更适用于您想要启动应用程序、向其提供所需的所有输入并读取其输出的情况。

正如其他答案指出的那样,您可以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
于 2012-04-23T19:40:32.587 回答
2

使用 subprocess 而不是 popen,然后您可以使用完整的命令行大大简化事情。

http://docs.python.org/library/subprocess.html

例如。

import subprocess as sub
f = open('/dev/null', 'w')
proc = sub.call("cat file | grep string", executable="/bin/bash", shell=True)
于 2012-04-23T19:32:15.933 回答