Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ensuring subprocesses are dead on exiting Python program

Is there a way to ensure all created subprocess are dead at exit time of a Python program? By subprocess I mean those created with subprocess.Popen().

If not, should I iterate over all of the issuing kills and then kills -9? anything cleaner?

like image 757
pupeno Avatar asked Nov 26 '08 10:11

pupeno


People also ask

How do you stop a subprocess run in Python?

To close a single subprocess in Python, use the kill() method. The kill() is a built-in method used for terminating a single subprocess. The kill() command keeps running in the background.

How do you kill a process in python subprocess?

subprocess. Popen. kill(proc) is exactly the same as proc. kill() FYI.

Does subprocess call wait?

The subprocess module provides a function named call. This function allows you to call another program, wait for the command to complete and then return the return code. It accepts one or more arguments as well as the following keyword arguments (with their defaults): stdin=None, stdout=None, stderr=None, shell=False.


2 Answers

You can use atexit for this, and register any clean up tasks to be run when your program exits.

atexit.register(func[, *args[, **kargs]])

In your cleanup process, you can also implement your own wait, and kill it when a your desired timeout occurs.

>>> 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! 

Note -- Registered functions won't be run if this process (parent process) is killed.

The following windows method is no longer needed for python >= 2.6

Here's a way to kill a process in windows. Your Popen object has a pid attribute, so you can just call it by success = win_kill(p.pid) (Needs pywin32 installed):

    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 
like image 105
monkut Avatar answered Sep 19 '22 01:09

monkut


On *nix's, maybe using process groups can help you out - you can catch subprocesses spawned by your subprocesses as well.

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 

Another consideration is to escalate the signals: from SIGTERM (default signal for kill) to SIGKILL (a.k.a kill -9). Wait a short while between the signals to give the process a chance to exit cleanly before you kill -9 it.

like image 37
orip Avatar answered Sep 21 '22 01:09

orip