Terminate Python Process and halt it's underlying os.system command line - python

I am running a script that launches a program via cmd and then, while the program is open, checks the log file of the program for errors. If any, close the program.
I cannot use taskkill command since I don't know the PID of the process and the image is the same as other processes that I don't want to kill.
Here is a code example:
import os, multiprocessing, time
def runprocess():
os.system('"notepad.exe"')
if __name__ == '__main__':
process = multiprocessing.Process(target=runprocess,args=[])
process.start()
time.sleep(5)
#Continuously checking if errors in log file here...
process_has_errors = True #We suppose an error has been found for our case.
if process_has_errors:
process.terminate()
The problem is that I want the notepad windows to close. It seems like the terminate() method will simply disconnect the process without closing all it's tasks.
What can I do to make sure to end all pending tasks in a process when terminating it, instead of simply disconnecting the process from those tasks?

You can use taskkill but you have to use the /T (and maybe /F) switch so all child processes of the cmd process are killed too. You get the process id of the cmd task via process.pid.

You could use a system call if you know the name of the process:
import os
...
if process_has_errors:
processName = "notepad.exe"
process.terminate()
os.system(f"TASKKILL /F /IM {processName}")

Related

How to make a program close it's currently running instance upon startup?

I have a command line program which I'd like to keep running until I open it again, so basically a program which first checks if there's currently any already running instance of itself and kill it.
I tried os.system('TASKKILL /F /IM program.exe') but it turned out to be stupid because it also kills itself.
The most reliable way to make sure there's only one instance of your application is to create a pid file in a known (fixed) location. This location will usually be in your application data folder or in the temporary directory. At startup, you should check if the pid file exists and if the pid contained there still exists and refers to your target process. If it exists, send a kill signal to it, then overwrite the file with your current pid before starting the rest of the application.
For extra safetiness, you may want to wait until the previous process have completely terminated. This can be done by either waiting/polling to check if the process with that pid still exists, or by polling for the killed process to delete its own pid file. The latter may be necessary if process shutdown are very lengthy and you want to allow the current process to already start working while the old process is shutting down.
You can use the psutil library. It simply iterates through all running processes, filter processes with a specific filename and if they have a different PID than the current process, then it kills them. It will also run on any platform, considering you have a right process filename.
import psutil
process_to_kill = "program.exe"
# get PID of the current process
my_pid = os.getpid()
# iterate through all running processes
for p in psutil.process_iter():
# if it's process we're looking for...
if p.name() == process_to_kill:
# and if the process has a different PID than the current process, kill it
if not p.pid == my_pid:
p.terminate()
If just the program filename is not unique enough, you may use the method Process.exe() instead which is returning the full path of the process image:
process_to_kill = "c:\some\path\program.exe"
for p in psutil.process_iter():
if p.exe() == process_to_kill:
# ...
Because my working stations don't have access to internet and installing packages is a mess, I ended up coming up with this solution:
import os
os.system('tasklist > location/tasks.txt')
with open('location/tasks.txt', 'r') as pslist:
for line in pslist:
if line.startswith('python.exe'):
if line.split()[1] != str(os.getpid()):
os.system(f'TASKKILL /F /PID {line.split()[1]}')
break
os.remove('location/tasks.txt')
It prints the output of the tasklist command to a file and then checks the file to see if there's a runnig python process with a different PID from it's own.
edit: Figured out I can do it with popen so it's shorter and there are no files involved:
import os
for line in os.popen('tasklist').readlines():
if line.startswith('python.exe'):
if line.split()[1] != str(os.getpid()):
os.system(f'taskkill /F /PID {line.split()[1]}')
break
You can use the process id of already running instance.
import os
os.system("taskkill /pid <ProcessID>")

python create subprocess (newbie)

I'm new to python, so here's what I'm looking to get done.
I would like to use python to manage some of my gameservers and start/stop them. For this I would like to run every gameserver in a own process.
What's the best way to create processes using python, so these processes can continue even if the main application is stopped?
To start a server I only need to execute shell code.
How can I get access after stopping my main application and restarting it to these processes?
I'm not sure if I understand the question completely, but maybe something like this?
Run process:
import subprocess
subprocess.Popen(['/path/gameserver']) #keeps running
And in another script you can use 'ps -A' to find the pid and kill (or restart) it:
import subprocess, signal
p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE)
out, err = p.communicate()
for line in out.splitlines():
if 'gameserver' in line:
pid = int(line.split(None, 1)[0])
os.kill(pid, signal.SIGKILL)
Check the subprocess module. There is a function called call. See here.
You may need to set the process to not be a daemon process.

Unable to kill process started by Python

After start.exe is executed by Python, the output of start.exe is displayed in the python stdout. However 5 seconds later, we do not see Quitting printed and the task is not killed.
Is there an easier way to terminate an exe that was originally started by Python? Like getting a handle for the exe executed and using that handle to kill the process.
import subprocess
import os
import time
subprocess.call(['.\\start.exe'])
time.sleep(5)
print("Quitting")
os.system("taskkill /im start.exe")
As you can see at the subprocess documentation, the call function blocks until the process completes.
I believe that you should use the Popen functions as it doesn't block, and provides you a process handle.
Then, you can kill it like this: p.kill(), where p is the result from the Popen function.
The reason is that subprocess.call will wait for your start.exe to complete before continuing your script.
You can get a popen object (with better functionality) to your process via:
import subprocess
import os
import time
process = subprocess.Popen(['.\\start.exe'])
time.sleep(5)
print("Quitting")
process.terminate()

python daemon thread is exiting when process is killed

I am starting a python script on one terminal and then from another terminal issuing a kill -9 to kill the process. I am hoping that even when the parent process is killed the thread will continue to execute and touch the file. But that is not happening. Any clue how I can achieve this?
import time,os
import threading
# Create your tests here.
def a(fname):
print "a"
time.sleep(20)
touch(fname)
def touch(fname, times=None):
with open(fname, 'a'):
os.utime(fname, times)
print "touched"
fname = "test.txt"
t = threading.Thread(target=a, args=(fname,))
t.setDaemon(True)
t.start()
t.join()
What you are trying is impossible, unfortunately. Threads can only run as long as their parent process runs. If you want to start executing some code from your script, but have that code continue executing after your script exits, you should move that code into a separate script and use the subprocess module to launch it. Specifically, you can use subprocess.Popen to launch the script without blocking to wait for it to complete:
subprocess.Popen(['./yourscript.py', '-a', 'opt'])

How to kill a process been created by subprocess in python?

Under Linux Ubuntu operating system, I run the test.py scrip which contain a GObject loop using subprocess by:
subprocess.call(["test.py"])
Now, this test.py will creat process. Is there a way to kill this process in Python?
Note: I don't know the process ID.
I am sorry if I didn't explain my problem very clearly as I am new to this forms and new to python in general.
I would suggest not to use subprocess.call but construct a Popen object and use its API: http://docs.python.org/2/library/subprocess.html#popen-objects
In particular:
http://docs.python.org/2/library/subprocess.html#subprocess.Popen.terminate
HTH!
subprocess.call() is just subprocess.Popen().wait():
from subprocess import Popen
from threading import Timer
p = Popen(["command", "arg1"])
print(p.pid) # you can save pid to a file to use it outside Python
# do something else..
# now ask the command to exit
p.terminate()
terminator = Timer(5, p.kill) # give it 5 seconds to exit; then kill it
terminator.start()
p.wait()
terminator.cancel() # the child process exited, cancel the hit
subprocess.call waits for the process to be completed and returns the exit code (integer) value , hence there is no way of knowing the process id of the child process. YOu should consider using subprocess.Popen which forks() child process.

Categories