简体   繁体   English

Python 子进程查杀

[英]Python subprocess killing

I have problem killing sub processes.我在杀死子进程时遇到问题。 The following piece of code is used for creating the sub process-以下代码用于创建子流程-

  while(not myQueue.empty()): 
        p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE)

I'm creating processes by iterating until the queue(which has commands in it) is empty.我通过迭代直到队列(其中包含命令)为空来创建进程。 The variable p is global and is an object of type Popen.变量 p 是全局变量,是 Popen 类型的 object。 Even though the command has done what it is supposed to do, I'm having problems with stop button which is not stopping the process as I expected.即使命令已经完成了它应该做的事情,我遇到了停止按钮的问题,它没有像我预期的那样停止进程。

The stop button code is as follows-停止按钮代码如下——

  stop=Button(textBoxFrame,text="Stop",width=5,command=stopAll)
  stop.grid(row=1,column=4)

The stopAll method is called by the above stop button which will kill the current subprocess p. stopAll 方法由上面的停止按钮调用,它将终止当前子进程 p。

  def stopAll():
        p.kill()

NOTE-There are no errors, Exceptions or any compiling problems.注意-没有错误、异常或任何编译问题。

UPDATE: The problem is that p.kill() was not killing the process I needed to kill.更新:问题是p.kill()没有杀死我需要杀死的进程。 I checked this with unix using >> ps aux .我使用 unix 使用>> ps aux检查了这个。 I have also made my program to output starting and killing PIDs, so that I can check them with ps aux .我还将我的程序设置为 output 启动和终止 PID,以便我可以使用ps aux检查它们。 I found the process that I need to kill was 6 PIDs away from p.pid , I tried killing the process like os.kill((p.pid)+6,signal.SIGKILL) which is working and stopping the correct process.我发现我需要杀死的进程距离p.pid有 6 个 PID,我尝试杀死像os.kill((p.pid)+6,signal.SIGKILL)这样的进程,它正在工作并停止正确的进程。 But I don't want to do in that way as there are chances that may cause different child processes getting killed.但我不想那样做,因为有可能导致不同的子进程被杀死。 I'm giving more details on my problem-我正在提供有关我的问题的更多详细信息-

The Queue I'm using here contains commands as I said earlier.我在这里使用的队列包含我之前所说的命令。 The command is something like this-命令是这样的-

    echo "Hello"|festival --tts

Festival is a speech synthesizer in unix and festival --tts gets user input from a file. Festival 是 unix 中的语音合成器, festival --tts从文件中获取用户输入。 I'm piping "Hello" to festival and it says the words correctly.我正在向音乐节发送"Hello" ,它正确地说出了这些话。 But p which is the process of performing the above command is killing echo and not festival .但是执行上述命令的过程p正在杀死echo而不是festival So please help me with killing the particular (festival) process.所以请帮助我杀死特定的(节日)过程。

I suspect you may be having issues as you're not declaring stopPressed inside your stopAll() function as global, by example,我怀疑您可能遇到问题,因为您没有在 stopAll() function 中将 stopPressed 声明为全局,例如,

>>> fred = '20'
>>> def updateFred(age):
...     fred=age
>>> updateFred(40)
>>> fred
'20'
>>> def updateFred(age):
...     global fred
...     fred=age
>>> updateFred(40)
>>> fred
40

Perhaps adding 'global stopPressed' at the start of stopAll() will help?也许在 stopAll() 的开头添加“global stopPressed”会有所帮助?

I think more code is needed.我认为需要更多代码。 I am not sure how you are handling the event of the button being pressed (suspecting a threading problem).我不确定您如何处理按下按钮的事件(怀疑是线程问题)。 Also, shouldn't be stopprcs be included inside the first loop instead of outside?另外,stopprcs 不应该包含在第一个循环中而不是外部吗? spacing problem (or is the problem just in here?).间距问题(或者问题就在这里?)。

As @aid mentioned, ifyou do not explicity make the handle a global you cannot change it for everyone else.正如@aid 所提到的,如果您没有明确地将句柄设为全局句柄,则您无法为其他所有人更改它。 Try this instead of your stopAll function试试这个而不是你的 stopAll function

def stopAll():
    global stopPressed
    stopPressed=True

I would suggest instead of messing with globals and what not is to create a class, such as我建议不要弄乱全局变量,而不是创建一个 class,例如

class GuiController(object):
    # if you want the stopPressed to be a static variable accross all
    # GuiController instances uncomment the next line and comment out the __init__
    #stopPressed = False
    def __init__(self):
        self.stopPressed=False
    def main(self):
        while(not myQueue.empty()): 
            p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE)
            while(p.returncode==None):
                if(stopPressed==True):
                    p.kill()
                    break
        self.stopPressed=False
    def stopAll(self):
        self.stopPressed=True

Since the festival program is in UNIX we can make use of preexec_fn.由于节日节目在 UNIX 中,我们可以使用 preexec_fn。 Festival was creating its own sub processes which made killing harder, So in this case making use of group id that identifies all the festival processes will solve it. Festival 正在创建自己的子进程,这使得杀戮变得更加困难,因此在这种情况下,使用标识所有节日进程的 group id 将解决它。 We can make a group of processes using the code below-我们可以使用下面的代码创建一组进程 -

   while(not myQueue.empty()): 
    p=Popen(myQueue.get(),shell=True, stdin=PIPE,preexec_fn=os.setsid)

stopAll now has the following code for killing group of child processes pointed by global variable p- stopAll 现在具有以下代码,用于杀死全局变量 p- 指向的子进程组

    os.killpg(os.getpgid(p.pid), signal.SIGKILL)

will kill the group of sub processes that are spawned.将杀死产生的子进程组。 Source: Working with subprocess资料来源:使用子流程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM