Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python子进程终止_Python_User Interface_Button_Tk_Kill Process - Fatal编程技术网

Python子进程终止

Python子进程终止,python,user-interface,button,tk,kill-process,Python,User Interface,Button,Tk,Kill Process,我在杀死子进程时遇到问题。下面的代码用于创建子流程- while(not myQueue.empty()): p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE) 我通过迭代创建进程,直到队列(其中包含命令)为空。变量p是全局变量,是Popen类型的对象。尽管命令已经完成了它应该做的事情,但我在stop按钮上遇到了问题,它并没有像我预期的那样停止进程 停止按钮代码如下所示- stop=Button(textB

我在杀死子进程时遇到问题。下面的代码用于创建子流程-

  while(not myQueue.empty()): 
        p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE)
我通过迭代创建进程,直到队列(其中包含命令)为空。变量p是全局变量,是Popen类型的对象。尽管命令已经完成了它应该做的事情,但我在stop按钮上遇到了问题,它并没有像我预期的那样停止进程

停止按钮代码如下所示-

  stop=Button(textBoxFrame,text="Stop",width=5,command=stopAll)
  stop.grid(row=1,column=4)
stopAll方法由上面的stop按钮调用,该按钮将终止当前子进程p

  def stopAll():
        p.kill()
注意:没有错误、异常或任何编译问题

更新: 问题是
p.kill()
没有终止我需要终止的进程。我使用unix使用ps aux检查了这一点。我还编制了输出启动和终止PID的程序,以便使用
ps aux
检查它们。我发现我需要终止的进程距离
p.pid
有6个pid,我尝试终止进程,就像
os.kill((p.pid)+6,signal.SIGKILL)
一样,它正在工作并停止正确的进程。但我不想这样做,因为有可能会导致不同的子进程被杀死。我会提供更多关于我问题的细节-

我在这里使用的队列包含我前面说过的命令。命令是这样的-

    echo "Hello"|festival --tts

Festival是unix中的语音合成器,
Festival--tts
从文件中获取用户输入。我正在向festival吹“Hello”,它说的话是正确的。但是执行上述命令的过程
p
正在杀死
echo
,而不是
festival
。因此,请帮助我消除特定的(节日)过程。

我认为需要更多的代码。我不确定您是如何处理按钮被按下的事件的(怀疑是线程问题)。另外,不应该包含在第一个循环内部而不是外部吗?间距问题(或者问题就在这里?)

我怀疑您可能遇到了一些问题,例如,您没有在stopAll()函数中将stopPressed声明为全局

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

也许在stopAll()的开头添加“global stopPressed”会有所帮助?

正如@aid所提到的,如果不明确地将句柄设置为全局句柄,则无法为其他所有人更改它。尝试使用此函数而不是stopAll函数

def stopAll():
    global stopPressed
    stopPressed=True
我建议不要与globals混为一谈,而是创建一个类,比如

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

由于festival程序在UNIX中,我们可以使用preexec_fn。Festival创建了自己的子流程,这使得杀戮更加困难,因此在本例中,使用标识所有Festival流程的组id将解决此问题。我们可以使用下面的代码创建一组进程-

   while(not myQueue.empty()): 
    p=Popen(myQueue.get(),shell=True, stdin=PIPE,preexec_fn=os.setsid)
stopAll现在有以下用于杀死由全局变量p指向的子进程组的代码-

    os.killpg(os.getpgid(p.pid), signal.SIGKILL)
将杀死生成的子进程组。
来源:

stopPressed和stopprcs不应该是同一个变量吗?@aid说了什么。但是仍然怀疑有线程问题。很抱歉,我更改了变量的名称以便于阅读。我现在做了一些修改。重点是,在函数中,如果不将变量声明为全局变量,python将创建一个同名的局部变量,而不是访问全局变量。是的,我明确地将其称为全局变量。但是kill()不起作用。我有类似的代码。我现在发现了问题,是p.kill()没有终止正确的进程。我将更新我的帖子以反映这一点。很可能,您是否正在使用纯Exception捕捉代码中的所有异常,如try:somecode()Exception:SomeHandling()您应该始终使用Exception:。。。如果您想捕获全部,因为一个裸的except也将捕获一个SIGINT。