The methods. .terminate() , .kill() the subprocess.Popen try to stop only the process itself:
#!/usr/bin/env python3 import subprocess import sys import time start = time.monotonic() process = subprocess.Popen([sys.executable or 'python', '-c', 'import time; time.sleep(30)']) assert process.poll() is None # process is alive process.terminate() process.wait() assert (time.monotonic() - start) < 30 # exited before timeout assert process.poll() is not None # process is dead and reaped
In this case, the child processes can continue to live, an example .
Popen() calling Popen() with the shell=True parameter, an implicit process is created ( cmd.exe , /bin/sh ), which starts the transferred command. If this is not a built-in / internal command, then you have at least two processes (the shell itself plus the program that it launched). .kill() kills the shell itself, while the child process can continue to live. On * nix, in this case, you can try to start the process in a separate group of processes and then send a signal to this group so that all processes are completed (similar to how Ctrl + C works in the database): How to terminate a python subprocess launched with shell = True . On Windows, you can try taskkill :
from subprocess import Popen, check_call process = Popen('py -c "import time; time.sleep(30)"', shell=True) check_call("TASKKILL /F /PID {pid} /T".format(pid=process.pid))
/T argument says that the taskkill is trying to kill both the process itself and any child processes that it has started. Using the /IM parameter, you can stop processes by name.
psutil module provides a portable way to kill child processes .
To close a new window created by the start command, upon completion of the child command, you can explicitly pass the /c parameter to cmd :
D:\> start /wait "title" cmd /c batch.cmd
You can add /B to start so that a new window is not created. If you used start to do something in the background, then you don’t need it in Python, just remove the start ( Popen() call does not wait until the process is complete). Similarly, if you do not need to run the internal command , you can do without the shell=True as a rule.
As an alternative to explicitly stopping, you can start processes so that child processes are automatically killed when the parent completes: Python: how to kill the child process (es) when parent dies? On Windows, this can be organized by assigning the created parent process to your Job object .
shell=True- returns the pid of the shell, not the process itself, so an option that can work isos.killpg- Yaroslav Surzhikovos.killpgnot supported (you can try sending a signal to the processes from the same console (startnew window opens):os.kill(pid, signal.CTRL_C_EVENT)(not tested)), although if the taskkill does not help , then more details are needed. - jfs