使用xterm时终止子进程

时间:2016-04-14 16:32:56

标签: python subprocess

主脚本是script.py,我在启动script.py时运行两个子进程,如下所示:

#PART ONE:
import subprocess

command = ["python", "first.py"]
command2 = ["python", "second.py"]
n = 5
for i in range(n):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    p2 = subprocess.Popen(command2, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    #PART TWO:
    while True: #or while p.returncode==None:
        output = p.stdout.readline().strip()
        print output
        if output == 'stop':
            print 'success'
            p.terminate()
            p2.terminate()
            break 

所以基本上我在子进程p打印'stop'时都停止了。一切都很好。我试图通过将'xterm','-e'分别添加到commandcommand2来实现同样的工作,不同的是在单独的终端中启动两个子进程。问题现在是p.stdout.readline().strip()我无法访问p打印的内容,因此我无法停止主脚本script.py中的子进程。我应该如何修改我的代码(特别是#PART TWO)以便使用command = ['xterm','-e','python','first.py']我仍然可以读取输出并在打印'stop'时终止它们?

所以基本上#PART ONE现在是:

#PART ONE:
import subprocess

command = ["xterm","-e","python", "first.py"]
command2 = ["xterm","-e","python", "second.py"]
n = 5
for i in range(n):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    p2 = subprocess.Popen(command2, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

问题是如何修改#PART TWO,以便可以读取输出,并在某些条件下终止进程。

2 个答案:

答案 0 :(得分:0)

一个简单的解决方案是将first.py的stdout重定向到临时文件。然后修改part2以从该文件中读取而不是stdout的管道。

或者,xterm手册页可能会提供一些信息。

答案 1 :(得分:0)

老实说,我不记得我把它放在一起的来源,但是我使用下面的类或者一些修改后的版本来做你所说的。据我所知,子进程模块不允许条件终止,除非你把进程放在一个线程中。同时管理线程和进程的最简单方法是将它们捆绑为一个类。

import os,subprocess,threading

class RunSubprocess(object):

    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None
        self.stdOut,self.stdErr = None,None

    def run(self,timeout=100):
        def target():
            self.process = subprocess.Popen(self.cmd,
                                            shell=True,
                                            stderr=subprocess.PIPE,
                                            stdout=subprocess.PIPE,
                                            universal_newlines=True,
                                            bufsize=4096)
        self.stdOut, self.stdErr = self.process.communicate()

    self.thread = threading.Thread(target=target)
    self.thread.start()

    ## wait                            
    if timeout != None:
        self.thread.join(timeout)
        if self.thread.is_alive():
            print('The subprocess was auto-terminated due to timeout')
            print("..."+self.process.poll())
            self.process.terminate()
            self.thread.join()

        return self.process.returncode
    return None

    def terminate(self):
        if self.thread.is_alive():
            self.process.terminate()
            self.thread.join()

if __name__ == '__main__':
    cmd = "echo '...started'; sleep 2; echo '... finished'"
    myProcess = RunSubprocess(cmd)

    returnCode = myProcess.run(timeout=10)
    myProcess.terminate()
    print(myProcess.stdOut)

所以我相信你可以修改这个类来启动两个脚本,并且可以紧密相连。