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。