有没有办法确保所有创建的子进程在Python程序的退出时间都死了?通过子进程,我指的是使用subprocess.Popen()创建的.
如果没有,我应该迭代所有发出的杀戮然后杀死-9?什么更干净?
您可以使用atexit,并注册在程序退出时要运行的任何清理任务.
atexit.register(func [,*args [,**kargs]])
在清理过程中,您还可以实现自己的等待,并在发生所需的超时时将其终止.
>>> import atexit >>> import sys >>> import time >>> >>> >>> >>> def cleanup(): ... timeout_sec = 5 ... for p in all_processes: # list of your processes ... p_sec = 0 ... for second in range(timeout_sec): ... if p.poll() == None: ... time.sleep(1) ... p_sec += 1 ... if p_sec >= timeout_sec: ... p.kill() # supported from python 2.6 ... print 'cleaned up!' ... >>> >>> atexit.register(cleanup) >>> >>> sys.exit() cleaned up!
注 - 如果此进程(父进程)被终止,则不会运行已注册的函数.
python> = 2.6不再需要以下windows方法
这是一种在Windows中杀死进程的方法.你的Popen对象有一个pid属性,所以你可以通过success = win_kill(p.pid)调用它(需要安装pywin32):
def win_kill(pid): '''kill a process by specified PID in windows''' import win32api import win32con hProc = None try: hProc = win32api.OpenProcess(win32con.PROCESS_TERMINATE, 0, pid) win32api.TerminateProcess(hProc, 0) except Exception: return False finally: if hProc != None: hProc.Close() return True
在*nix上,也许使用进程组可以帮助你 - 你也可以捕获子进程产生的子进程.
if __name__ == "__main__": os.setpgrp() # create new process group, become its leader try: # some code finally: os.killpg(0, signal.SIGKILL) # kill all processes in my group
另一个考虑因素是升级信号:从SIGTERM(默认信号kill
)到SIGKILL(aka kill -9
).在信号之间等待一会儿,让过程有机会在你之前干净地退出kill -9
.
这subprocess.Popen.wait()
是确保他们死亡的唯一方法.实际上,POSIX OS要求您等待您的孩子.许多*nix将创建一个"僵尸"过程:一个死孩子,父母没有等待.
如果孩子写得合理,它就会终止.孩子们常常从PIPE上读到.关闭输入是一个很大的暗示,孩子应该关闭购物和退出.
如果孩子有虫子并且没有终止,你可能不得不杀死它.你应该修复这个bug.
如果孩子是"永远服务"循环,并且不是为了终止,你应该杀死它或者提供一些输入或消息来强制它终止.
编辑.
在标准操作系统中,你有os.kill( PID, 9 )
.Kill -9很苛刻,BTW.如果你能用SIGABRT(6?)或SIGTERM(15)杀死它们,那就更有礼貌了.
在Windows操作系统中,您没有os.kill
可行的功能.查看此ActiveState配方以终止Windows中的进程.
我们有子进程是WSGI服务器.要终止它们,我们在特殊URL上进行GET; 这导致孩子清理并退出.