I want open a program (ex: calculator) and keep tracking his process as the pid, name, etc.
But, after calling the subprocess.Popen(), the process id is killed after few time.
So i want to initialize this program and get the process id and other informations and kill the process only if the user close the application (in this case, the calculator).
import subprocess
import psutil
process = subprocess.Popen('C:\Windows\System32\calc')
while psutil.pid_exists(process.pid):
print('Process running')
print('Done')
Please note that I only got Mac right now so the code runs correctly on it. However, I think it will function properly on Windows as well if you insert the file path of the application correctly.
For Windows
import subprocess
import psutil
import time
print(psutil.__version__) # tested on 5.9.0
process = subprocess.Popen('C:\Windows\System32\calc')
# wait a moment to make sure that the app is open
time.sleep(1)
is_running = True
while is_running:
# check if the app is running
is_running = "calc" in (p.name() for p in psutil.process_iter())
print('Process running')
print('Done')
For MAC
import subprocess
import psutil
import time
print(psutil.__version__) # tested on 5.9.0
process = subprocess.Popen(['open', '/System/Applications/Calculator.app'])
# wait a moment to make sure that the app is open
time.sleep(1)
is_running = True
while is_running:
# check if the app is running
is_running = "Calculator" in (p.name() for p in psutil.process_iter())
print('Process running')
print('Done')
Related
I'm relatively new to python so please forgive early level understanding!
I am working to create a kind of flag file. Its job is to monitor a Python executable, the flag file is constantly running and prints "Start" when the executable started, "Running" while it runs and "Stop" when its stopped or crashed, if a crash occurs i want it to be able to restart the script. so far i have this down for the Restart:
from subprocess import run
from time import sleep
# Path and name to the script you are trying to start
file_path = "py"
restart_timer = 2
def start_script():
try:
# Make sure 'python' command is available
run("python "+file_path, check=True)
except:
# Script crashed, lets restart it!
handle_crash()
def handle_crash():
sleep(restart_timer) # Restarts the script after 2 seconds
start_script()
start_script()
how can i implement this along with a flag file?
Not sure what you mean with "flag", but this minimally achieves what you want.
Main file main.py:
import subprocess
import sys
from time import sleep
restart_timer = 2
file_path = 'sub.py' # file name of the other process
def start():
try:
# sys.executable -> same python executable
subprocess.run([sys.executable, file_path], check=True)
except subprocess.CalledProcessError:
sleep(restart_timer)
return True
else:
return False
def main():
print("starting...")
monitor = True
while monitor:
monitor = start()
if __name__ == '__main__':
main()
Then the process that gets spawned, called sub.py:
from time import sleep
sleep(1)
print("doing stuff...")
# comment out to see change
raise ValueError("sub.py is throwing error...")
Put those files into the same directory and run it with python main.py
You can comment out the throwing of the random error to see the main script terminate normally.
On a larger note, this example is not saying it is a good way to achieve the quality you need...
So basically, i want python to run another programm and wait till that program is not visible in the taskmanger and then continue with the script.
Any Ideas?
As #eryksun suggested, the subprocess module can handle the waiting as well:
import subprocess
process = subprocess.Popen(["notepad.exe"], shell=False)
process.wait()
print ("notepad.exe closed")
You could use something like this, tracking the process id of the opened program:
import subprocess, win32com.client, time
wmi=win32com.client.GetObject('winmgmts:')
process = subprocess.Popen(["notepad.exe"], shell=False)
pid = process.pid
flag = True
while flag:
flag = False
for p in wmi.InstancesOf('win32_process'):
if pid == int(p.Properties_('ProcessId')):
flag = True
time.sleep(.1)
print ("notepad.exe closed")
Output when notepad is closed:
notepad.exe closed
>>>
Here's an example of a simple way to see if something is running on Windows that uses its built-in tasklist command:
import os
import subprocess
target = 'notepad.exe'
results = subprocess.check_output(['tasklist'], universal_newlines=True)
if any(line.startswith(target) for line in results.splitlines()):
print(target, 'is running')
else:
print(target, 'is *not* running')
It can be done with pywinauto:
from pywinauto import Application
app = Application().connect(process=pid) # or connect(title_re="") or other options
app.wait_for_process_exit(timeout=50, retry_interval=0.1)
If I wanted to have a program that detects program running such as 'chrome.exe' then opens a program message.txt in this case
Psuedocode:
import os
if "chrome.exe" is running:
os.startfile("message.txt")
You could you below too as furas said. Thanks furas. :smile:
import psutil as psutil
for proc in psutil.process_iter():
proc_name = proc.name()
if proc_name == 'chrome.exe':
print('chrome is running now.')
# open your program in this position
else:
print(proc_name)
You could use wmi package to check running process in windows like below snippet.
import wmi
c = wmi.WMI()
for process in c.Win32_Process():
if process.Name == 'chrome.exe':
print('chrome is running now.')
# open your program in this position
else:
print(process.Name)
I need to launch a GUI application, wait for the application to quit, and then start the other processes.
import subprocess
res = subprocess.check_output(["/usr/bin/open", "-a", "/Applications/Mou.app", "p.py"])
print "Finished"
... start the other processes
However, the process returns right away without waiting for the Mou.app to finish.
How can I make the python process to wait? I use Mac OS X.
According to the open man page, the -W flag causes open to wait until the app exits.
Therefore try:
import subprocess
res = subprocess.check_output(["/usr/bin/open", "-a", "-W", "/Applications/Mou.app", "p.py"])
print "Finished"
I'm trying to write a Python script that will enable me to start the Google App Engine dev_appserver using coverage.py, fetch the /test url from the app that I launch, wait for the server to finish returning the page, then shutdown the dev_appserver, and then generate a report.
My challenge is how to launch the dev_appserver in the background so that I can do the http fetch and then how to shut down the dev_appserver before generating my report.
I'm heading towards something like this:
# get_gae_coverage.py
# Launch dev_appserver with coverge.py
coverage run --source=./ /usr/local/bin/dev_appserver.py --clear_datastore --use_sqlite .
#Fetch /test
urllib.urlopen('http://localhost:8080/test').read()
# Shutdown dev_appserver somehow
# ??
# Generate coverage report
coverage report
What is the best way to write a python script to do this?
You should go with subprocess Popen
import os
import signal
import subprocess
coverage_proc = subprocess.Popen(
['coverage','run', your_flag_list]
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
time.sleep(5) #Find the correct sleep value
urllib.urlopen('http://localhost:8080/test').read()
time.sleep(1)
os.kill(coverage_proc.pid, signal.SIGINT)
Here you can find another approach to test if the server is up and running:
line = proc.stdout.readline()
while '] Running application' not in line:
line = proc.stdout.readline()
threading is the way to accomplish such a kind of task. Namely, you start the dev_appserver in a thread or in the main thread and as it is running, run and collect the results using the coverage module and then kill the dev_appserver python process in another thread and you will have results from coverage.
Here is sample snippet, which runs the dev_appserver.py in a thread and then waits for 10 seconds before and then it kills the python process. You can modify the end method in a suitable wherein the instead of waiting for 10 seconds, it waits for few seconds (in order to let the python process start) and then start doing the coverage testing and after it is done, kill the appserver and finish coverage.
import threading
import subprocess
import time
hold_process = []
def start():
print 'In the start process'
proc = subprocess.Popen(['/usr/bin/python','dev_appserver.py','yourapp'])
hold_process.append(proc)
def end():
time.sleep(10)
proc = hold_process.pop(0)
print 'Killing the appserver process'
proc.kill()
t = threading.Thread(name='startprocess',target=start)
t.deamon = True
w = threading.Thread(name='endprocess',target=end)
t.start()
w.start()
t.join()
w.join()