Can I get the PID of program launched by a subprogram? - python

My python script runs a program, let's call it X.exe
from subprocess import Popen
process = Popen('D:X.exe')
I can get its PID via
process.pid
After some time (which I know) X.exe launches another program - Y.exe. Can I get the PID of the Y.exe process? NOTE: I DON'T KNOW WHAT THE Y.exe WINDOW WILL BE NAMED

you can see the children of a process using psutil simply as follows.
import psutil
import subprocess
import time
proc = subprocess.Popen("start /wait", shell=True) # start another cmd.exe
time.sleep(0.5) # wait for child to start
process_object = psutil.Process(proc.pid)
children = process_object.children()
print(f"child pid is {children[0].pid}")
proc.wait()
child pid is 18292

Related

kill process do not kill the subprocess and do not close a terminal window

I am working on UBUNTU and I have file main.py with a code inside:
#!/usr/bin/env python3
# coding=utf-8
import os
import time
from subprocess import Popen, PIPE, call, signal
base_path = os.path.abspath('')
path_to_file = base_path + '/test_subprocess.py'
p = Popen(['gnome-terminal', "--", path_to_file])
time.sleep(2)
os.kill(p.pid, signal.SIGKILL)
I have test_subprocess.py with code like that:
#!/usr/bin/env python3
# coding=utf-8
import time
def print_message():
while True:
print('I am working!')
time.sleep(0.5)
print_message()
I tried to kill the subprocess but after
os.kill(p.pid, signal.SIGKILL)
subprocess is still working and prints 'I am working!'
How can I finish subprocess and how to close gnome terminal?
If I selected completely wrong way. Can you show me working example?
New version of test_subprocess.py
#!/usr/bin/env python3
# coding=utf-8
import sys
from subprocess import signal
import time
def print_message():
while True:
print('I am working!')
time.sleep(0.5)
if signal.SIGKILL: # it is braking a loop when parent process terminate!
print('I am killing self!')
break
print_message()
Should I do it like above?
You could try the following:
p = Popen(['gnome-terminal', "--", path_to_file])
PIDs = p.pid
os.system("kill {0}".format(PIDs))
Popen.pid The process ID of the child process.
Note that if you set the shell argument to True, this is the process
ID of the spawned shell.
http://docs.python.org/library/subprocess.html
This will at least kill the correct process. Not sure if it will close the terminal.
Edit: to kill the process and close the terminal:
p = Popen(['gnome-terminal', '--disable-factory', '-e', path_to_file], preexec_fn=os.setpgrp)
os.killpg(p.pid, signal.SIGINT)
Credit to https://stackoverflow.com/a/34690644/15793575, whih I modified for your command:
--disable-factory is used to avoid re-using an active terminal so that we can kill newly created terminal via the subprocess handle
os.setpgrp puts gnome-terminal in its own process group so that
os.killpg() could be used to send signal to this group
Popen.pid
The process ID of the child process.
Note that if you set the shell argument to True, this is the process
ID of the spawned shell.
Try setting the shell argument of the Popen constructor to False. (p = Popen(['gnome-terminal', "--", path_to_file]) -> p = Popen(['gnome-terminal', "--", path_to_file], shell=False)). I had a similar issue not long ago - this fixed it for me.

How to get the pid of the process started by subprocess.run and kill it

I'm using Windows 10 and Python 3.7.
I ran the following command.
import subprocess
exeFilePath = "C:/Users/test/test.exe"
subprocess.run(exeFilePath)
The .exe file launched with this command, I want to force-quit when the button is clicked or when the function is executed.
Looking at a past question, it has been indicated that the way to force quit is to get a PID and do an OS.kill as follows.
import signal
os.kill(self.p.pid, signal.CTRL_C_EVENT)
However, I don't know how to get the PID of the process started in subprocess.run.
What should I do?
Assign a variable to your subprocess
import os
import signal
import subprocess
exeFilePath = "C:/Users/test/test.exe"
p = subprocess.Popen(exeFilePath)
print(p.pid) # the pid
os.kill(p.pid, signal.SIGTERM) #or signal.SIGKILL
In same cases the process has children
processes. You need to kill all processes to terminate it. In that case you can use psutil
#python -m pip install —user psutil
import psutil
#remember to assign subprocess to a variable
def kills(pid):
'''Kills all process'''
parent = psutil.Process(pid)
for child in parent.children(recursive=True):
child.kill()
parent.kill()
#assumes variable p
kills(p.pid)
This will kill all processes in that PID

How do I know when a child process died in python3 on windows platform?

In linux I use subprocess.Popen to create a child process, and define a signal handler for SIGCHLD. When the child process died, parent process recieves SIGCHLD signal and the handler will do sth.
But on Windows there's no SIGCHLD signal, how can I know when the child process exited?
You can verify with TASKLIST FI(Filter) method that a given pid exist or not.
so the idea is
1) Generate a process.pid
2) See the status of PID with TASK list filter function
e.g.
TASKLIST /FI "PID eq 6228"
3) Kill the pid
4) see the status of pid again, it should not exist
below is the code, which will do the same
from subprocess import Popen,PIPE,CREATE_NEW_CONSOLE
import subprocess
command='cmd /K '
#This will open a new command prompt window
p1=Popen(command,creationflags=subprocess.CREATE_NEW_CONSOLE)
#printing the pid value
print p1.pid
# created a function to Verify if the pid exist
def check_pid():
command1="TASKLIST /FI "+ '"PID eq '+ str(p1.pid)+'"'
p2=Popen(command1,stdout=PIPE)
out=p2.communicate()[0]
print out
#Kill the pid
import subprocess
subprocess.Popen('taskkill /F /T /PID %i' % p1.pid)
#wait for some time and see if the pid exist
import time
time.sleep(3)
check_pid()

Can I close the CMD window that opened with subprocess.Popen in Python?

I have a program that need to run small tasks in new CMDs.
For example:
def main()
some code
...
proc = subprocess.Popen("start.bat")
some code...
proc.kill()
subprocess,Popen opens a new cmd window and runs "start.bat" in it.
proc.kill() kills the process but doesn't close the cmd window.
Is there a way to close this cmd window?
I thought about naming the opened cmd window so i can kill it with the command:
/taskkill /f /im cmdName.exe
Is it possible ?if no, What do you suggest ?
Edit, Added Minimal, Complete, and Verifiable example:
a.py:
import subprocess,time
proc = subprocess.Popen("c.bat",creationflags=subprocess.CREATE_NEW_CONSOLE)
time.sleep(5)
proc.kill()
b.py
while True:
print("IN")
c.bat
python b.py
that's expected when a subprocess is running. You're just killing the .bat process.
You can use psutil (third party, use pip install psutil to install) to compute the child processes & kill them, like this:
import subprocess,time,psutil
proc = subprocess.Popen("c.bat",creationflags=subprocess.CREATE_NEW_CONSOLE)
time.sleep(5)
pobj = psutil.Process(proc.pid)
# list children & kill them
for c in pobj.children(recursive=True):
c.kill()
pobj.kill()
tested with your example, the window closes after 5 seconds
here is another way you can do it
import subprocess
from subprocess import Popen,CREATE_NEW_CONSOLE
command ='cmd'
prog_start=Popen(command,creationflags=CREATE_NEW_CONSOLE)
pidvalue=prog_start.pid
#this will kill the invoked terminal
subprocess.Popen('taskkill /F /T /PID %i' % pidvalue)

Is there a module can be used as FindWindow API in python

On Windows there is a WinAPI: FindWindow that you can use to get window handle of a existing window and use this handle to send message to it. Is there a python module can do that too? Find a window & communicate with it?
If this module do exist, could the same mechainsm be able applied on Ubuntu too?
Thanks a lot!
You can execute your commands with a subprocess:
import subprocess
import time
process = subprocess.Popen("echo 'start' & sleep 60 & echo 'stop'", shell=True)
time.sleep(60) # Maybe you want a timer...
The you have two options of closing, use terminate or kill methods in the Popen returned object or simulate a Ctrl. + C
import subprocess
import time
process = subprocess.Popen(cmd, shell=True)
time.sleep(5)
process.terminate() # Or kill
Simulate de ctrl + c:
import subprocess
import time
import os
import signal
process = subprocess.Popen(cmd, shell=True)
time.sleep(5)
os.kill(process.pid, signal.SIGINT) # Ctrl. + C
If you want to get the output you can use:
process.communicate()[0].strip()
Which gives you a string.
If you want a console GUI, you can use a command like:
gnome-terminal -x sh yourCommand
Or the equivalent for the terminal you have installed.

Categories