The code below to kill a process opened using subprocess.Popen() works on Linux.
import os
import signal
import subprocess
# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE,
shell=True, preexec_fn=os.setsid)
os.killpg(os.getpgid(pro.pid), signal.SIGTERM) # Send the signal to all the process groups
Unfortunately, it does not work on Windows. The process refused to be killed. How to modify the code such that the process can be killed on Windows?
I am using Windows 10, Python 3.8 on Anaconda.
USE subprocess.Popen.terminate() TO TERMINATE A SUBPROCESS
Related
In Python, external processes can be started easily using the subprocess module. For instance on Windows:
command = 'external_app'
my_process = subprocess.Popen(
command,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
shell=True,
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
universal_newlines=True)
To kill the process, we can run:
os.kill(my_process.pid, signal.CTRL_BREAK_EVENT)
This works fine using the command-line interpreter of Python (python.exe). But if I like to start and stop processes from within a graphical Python application without a command-line window using pythonw.exe the problem occurs that I can’t stop the process with os.kill anymore.
How can I kill an external process on Windows with pythonw.exe?
I'm trying to use python psutil library to create and kill process. My script starts an process, and then tries to kill started subprocess. I run same code under Windows and Linux. Under Windows everything works well. Under Linux psutils starts subprocess correctly(so started app is script's child and it executed with same privileges as the script, but when I try to kill the process psutil detaches from the process but not kills. Here is starting app code:
self.__proc = psutil.Popen(cmd, cwd=working_directory, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
After this I try to kill started child process:
self.__proc.kill()
self.__proc = None
I got same behavior using this:
while psutil.pid_exists(pid):
p = psutil.Process(pid)
if p is not None:
p.kill()
Can anyone explain why I can't kill process started by me? What I'm doing wrong?
I'm using Python 2.7.
I'm completely confused between subprocess.call() , subprocess.Popen(), subprocess.check_call().
Which is blocking and which is not ?
What I mean to say is if I use subprocess.Popen() whether the parent process waits for the child process to return/exit before it keep on its execution.
How does shell=True affect these calls?
Popen is nonblocking. call and check_call are blocking.
You can make the Popen instance block by calling its wait or communicate method.
If you look in the source code, you'll see call calls Popen(...).wait(), which is why it is blocking.
check_call calls call, which is why it blocks as well.
Strictly speaking, shell=True is orthogonal to the issue of blocking. However, shell=True causes Python to exec a shell and then run the command in the shell. If you use a blocking call, the call will return when the shell finishes. Since the shell may spawn a subprocess to run the command, the shell may finish before the spawned subprocess. For example,
import subprocess
import time
proc = subprocess.Popen('ls -lRa /', shell=True)
time.sleep(3)
proc.terminate()
proc.wait()
Here two processes are spawned: Popen spawns one subprocess running the shell. The shell in turn spawns a subprocess running ls. proc.terminate() kills the shell, but the subprocess running ls remains. (That is manifested by copious output, even after the python script has ended. Be prepared to kill the ls with pkill ls.)
Killing subprocess created with shell=True passed to subprocess.Popen's constructor under Linux kills only shell and not the process created by shell (see How to terminate a python subprocess launched with shell=True). However python -c "import subprocess; subprocess.Popen(['ping', '-t', 'google.com'], shell=True).terminate()" run under Windows Vista x64 SP3 and Python 2.7.3 64bit kills the ping process. Under Windows subprocess.Popen.terminate() calls TerminateProcess. However documentation of this function states
Terminates the specified process and all of its threads.
There is no mention about terminating whole process tree. What am I missing?
I think this is only with the one-liner you give, and my observations suggest that the ping does not even get started. If you run as a script (Windows 7):
import subprocess
proc = subprocess.Popen(['ping', '-t', 'google.com'], shell=True)
raw_input("<RETURN> to terminate")
proc.terminate()
raw_input("<RETURN> to end")
Then the proc.terminate() only terminates the shell, it does not terminate the ping!
However, if you set shell=False then it behaves as expected - it terminates the ping. Same behaviour on Python 2.7 and 3.2.
Edit: I tried this code as a one-liner as well, and got the same results as the questioner. I hate sleep hacks, but this works:
python -c "import subprocess,time;proc = subprocess.Popen(['ping','-t', 'google.com'], shell=True);time.sleep(1);proc.terminate()"
I'm actually running a subprocess from a python program using Popen
proc= subprocess.Popen("xterm -e python script.py", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
And when this process is running on xterm, we can kill it using Ctrl+C, is there a way to send other signals using (Ctrl+Z and fg,...) to resume and continue the job?
Another solution would be running this process in another terminal, without using xterm -e is this possible?
Any other solution would be helpful.
Thanks
You could do it programatically in psutil
import psutil
p = psutil.Pocesss(proc.pid)
p.suspend()
p.resume()
With Python2.6+
# send ctrl+c
popen.send_signal(signal.SIGINT)