在Python 2.5上可靠地终止子进程

在Python 2.5上可靠地终止子进程,python,subprocess,Python,Subprocess,我有一个脚本,它反复运行一个Ant构建文件,并将输出转换成可解析的格式。当我使用Popen创建子流程时,有一个很小的时间窗口,点击Ctrl+C将终止脚本,但不会终止运行Ant的子流程,留下一个僵尸,将输出打印到控制台,只能使用任务管理器终止。一旦Ant开始打印输出,按Ctrl+C将永远杀死我的脚本和Ant。有没有一种方法可以使按下Ctrl+C键总是杀死运行Ant的子进程,而不会留下僵尸 另外值得注意的是:我有一个SIGINT处理程序,它在调用exit(0)之前执行一些清理操作。如果我使用os.k

我有一个脚本,它反复运行一个Ant构建文件,并将输出转换成可解析的格式。当我使用Popen创建子流程时,有一个很小的时间窗口,点击Ctrl+C将终止脚本,但不会终止运行Ant的子流程,留下一个僵尸,将输出打印到控制台,只能使用任务管理器终止。一旦Ant开始打印输出,按Ctrl+C将永远杀死我的脚本和Ant。有没有一种方法可以使按下Ctrl+C键总是杀死运行Ant的子进程,而不会留下僵尸

另外值得注意的是:我有一个SIGINT处理程序,它在调用exit(0)之前执行一些清理操作。如果我使用
os.kill(p.pid,signal.SIGTERM)
(非SIGINT)手动终止处理程序中的子进程,那么我可以在子进程通常会僵化的情况下成功终止它。然而,一旦Ant开始生成输出,当您点击Ctrl+C时,您将从子流程中获得一个stacktrace,在这里它无法终止子流程本身,因为我已经终止了它


编辑:我的代码看起来像:

p = Popen('ls')
def handle_sig_int(signum, stack_frame):
    # perform cleanup
    os.kill(p.pid, signal.SIGTERM)
    exit(0)
signal.signal(signal.SIGINT, handle_sig_int)

p.wait()
如果触发错误,将产生以下堆栈跟踪:

File "****.py", line ***, in run_test
  p.wait()
File "/usr/lib/python2.5/subprocess.py", line 1122, in wait
  pid, sts = os.waitpid(self.pid, 0)
File "****.py", line ***, in handle_sig_int
  os.kill(p.pid, signal.SIGTERM)
我通过捕获p引发的操作错误来修复它。等待并退出:

try:
    p.wait()
except OSError:
    exit('The operation was interrupted by the user')
这似乎在我的绝大多数测试运行中都有效。我偶尔会得到一个
uname:write error:breaked pipe
,尽管我不知道是什么原因造成的。如果我恰好在子进程开始显示输出之前计时Ctrl+C,则似乎会发生这种情况。

在SIGTERM处理程序中调用
p.terminate()

 if p.poll() is None: # Child still around?
     p.terminate() # kill it
[EDIT]因为您一直使用Python 2.5,所以请使用
os.kill(p.pid,signal.SIGTERM)
而不是
p.terminate()
。该检查应确保您没有收到异常(或减少收到异常的次数)


为了使它更好,您可以捕获异常并检查消息。如果它表示“未找到子进程”,则忽略异常。否则,请使用
raise
(无参数)重新播放它。

这是我在意识到Python2.6中添加了p.terminate()之前首先尝试的,而我仍然停留在2.5上。不幸的是,我无法升级Python。我最终尝试了一下对p.wait()的调用,并在捕获到一个操作错误时带着错误退出,从而使Python正常工作。