Python子进程查杀
Posted
技术标签:
【中文标题】Python子进程查杀【英文标题】:Python subprocess killing 【发布时间】:2011-10-26 16:44:33 【问题描述】:我在杀死子进程时遇到问题。以下代码用于创建子流程-
while(not myQueue.empty()):
p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE)
我通过迭代直到队列(其中包含命令)为空来创建进程。变量 p 是全局变量,是 Popen 类型的对象。即使命令完成了它应该做的事情,我也遇到了停止按钮的问题,它没有像我预期的那样停止进程。
停止按钮代码如下-
stop=Button(textBoxFrame,text="Stop",width=5,command=stopAll)
stop.grid(row=1,column=4)
stopAll 方法由上面的停止按钮调用,它将终止当前子进程 p。
def stopAll():
p.kill()
注意-没有错误、异常或任何编译问题。
更新:
问题是p.kill()
没有杀死我需要杀死的进程。我使用>> ps aux
在 unix 上检查了这一点。我还编写了我的程序来输出启动和终止 PID,以便我可以使用ps aux
检查它们。我发现我需要杀死的进程距离p.pid
有 6 个 PID,我尝试杀死像 os.kill((p.pid)+6,signal.SIGKILL)
这样的进程,它正在工作并停止正确的进程。但我不想那样做,因为有可能导致不同的子进程被杀死。我正在提供有关我的问题的更多详细信息-
我在这里使用的队列包含我之前所说的命令。命令是这样的-
echo "Hello"|festival --tts
Festival 是 unix 中的语音合成器,festival --tts
从文件中获取用户输入。我正在向音乐节发送"Hello"
,它正确地说出了这些话。但是执行上述命令的进程p
正在杀死echo
而不是festival
。所以请帮我杀死特定的(节日)进程。
【问题讨论】:
“stopPressed”和“stopprcs”不应该是同一个变量吗? @aid 说了什么。但也仍然怀疑是线程问题。 对不起,我更改了变量的名称以使其更易于阅读。我现在已经做出改变了。 【参考方案1】:我怀疑您可能遇到问题,因为您没有在 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”会有所帮助?
【讨论】:
重点是,在函数中,如果不将变量声明为全局变量,那么python会创建一个同名的局部变量,而不是访问全局变量。 是的,我确实明确表示它是全球性的。但是 kill() 不起作用。【参考方案2】:我认为需要更多代码。我不确定您如何处理按下按钮的事件(怀疑是线程问题)。另外,stopprcs 不应该包含在第一个循环中而不是外部吗?间距问题(或者问题就在这里?)。
【讨论】:
【参考方案3】:正如@aid 提到的,如果您没有明确地将句柄设为全局句柄,则您无法为其他所有人更改它。试试这个而不是你的 stopAll 函数
def stopAll():
global stopPressed
stopPressed=True
我建议不要弄乱全局变量,而不要创建一个类,例如
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
【讨论】:
我有和你类似的代码。我现在发现了问题,它是 p.kill() 没有杀死正确的进程。我将更新我的帖子以反映这一点。 万一,您是否使用裸异常捕获代码中的所有异常,例如 try: somecode() except: somehanding() 您应该始终使用 except Exception: ... 如果您想要捕获所有,因为一个裸的 except 也会捕获一个 SIGINT。【参考方案4】:由于节日程序在 UNIX 中,我们可以使用 preexec_fn。 Festival 正在创建自己的子进程,这使得杀戮变得更加困难,因此在这种情况下,使用标识所有节日进程的 group 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)
将杀死产生的子进程组。 来源:Working with subprocess
【讨论】:
以上是关于Python子进程查杀的主要内容,如果未能解决你的问题,请参考以下文章
python subprocess模块 监控子进程的2种方式 忙等待和立即返回同时设置子进程超时
Windows 上的 Python 子进程:启动子进程“cmd.exe”并为其提供 bat 文件,停止主进程执行