Reputation: 1796
I want to start several subprocesses with a programm, i.e. a module foo.py
starts several instances of bar.py
.
Since I sometimes have to terminate the process manually, I need the process id to perform a kill command.
Even though the whole setup is pretty “dirty”, is there a good pythonic way to obtain a process’ pid
, if the process is started via os.system
?
foo.py:
import os
import time
os.system("python bar.py \"{0}\ &".format(str(argument)))
time.sleep(3)
pid = ???
os.system("kill -9 {0}".format(pid))
bar.py:
import time
print("bla")
time.sleep(10) % within this time, the process should be killed
print("blubb")
Upvotes: 13
Views: 35433
Reputation: 5932
Here I am presenting a script, where I am running a script with gnome terminal and then later I am terminating the scbscript terminal.
import os
import subprocess
import signal
import time
import psutil
def kill_process_tree(pid, sig=signal.SIGTERM):
try:
parent = psutil.Process(pid)
for child in parent.children(recursive=True):
child.kill()
parent.kill()
except psutil.NoSuchProcess:
pass
script_name = 'my_program.py'
command = ["gnome-terminal", "--", "python3", script_name]
# Start the gnome-terminal with the script using subprocess.Popen
process = subprocess.Popen(command)
print(f"Running gnome-terminal process: {process.pid}")
# Wait for a few seconds to let the process start
time.sleep(5)
# Find the PIDs of the script running in the terminal
try:
script_pids = subprocess.check_output(["pgrep", "-f", script_name]).strip().split()
script_pids = [int(pid) for pid in script_pids]
print(f"Script PIDs: {script_pids}")
except subprocess.CalledProcessError:
print(f"Could not find PID for the script {script_name}")
script_pids = []
# Kill the gnome-terminal process
print(f"Killing gnome-terminal process, pid: {process.pid}")
kill_process_tree(process.pid)
# If script PIDs were found, kill the script processes
for script_pid in script_pids:
print(f"Killing script process, pid: {script_pid}")
kill_process_tree(script_pid)
In GNOME terminal, the terminal will start another process, the script, and by simply killing the terminal process might not kill the script running inside it. So we need to get the process id of the script itself along with the terminal.
Hope this clears with the above example.
Upvotes: 0
Reputation: 41
Sharing my solution in case it can help others:
I took the info from this page to run a fortran exe in the background. I tried to use os.forkpty to get the pid of it, but it didnt give the pid of my process. I cant use subprocess, because I didnt find out how it would let me run my process on the background.
With help of a colleague I found this:
exec_cmd = 'nohup ./FPEXE & echo $! > /tmp/pid'
os.system(exec_cmd)
In case of wanting to append pids to the same file, use double arrow.
Upvotes: 4
Reputation: 803
You could use os.forkpty()
instead, which, as result code, gives you the pid and fd for the pseudo terminal. More documentation here: http://docs.python.org/2/library/os.html#os.forkpty
Upvotes: 3
Reputation: 369134
os.system
return exit code. It does not provide pid of the child process.
Use subprocess
module.
import subprocess
import time
argument = '...'
proc = subprocess.Popen(['python', 'bar.py', argument], shell=True)
time.sleep(3) # <-- There's no time.wait, but time.sleep.
pid = proc.pid # <--- access `pid` attribute to get the pid of the child process.
To terminate the process, you can use terminate
method or kill
. (No need to use external kill
program)
proc.terminate()
Upvotes: 17