Running else loop once - python

So i have a script with the code
import os
import subprocess
import psutil
def checkIfProcessRunning(processName):
'''
Check if there is any running process that contains the given name processName.
'''
#Iterate over the all the running process
for proc in psutil.process_iter():
try:
# Check if process name contains the given name string.
if processName.lower() in proc.name().lower():
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False;
Then after executes
while True:
if checkIfProcessRunning('TDR'):
print('TDR (tdr.exe) is running')
else:
print('TDR (tdr.exe) is not running')
subprocess.call("cmd /c data.vbs") # Executes other code
This whole script detects if the process tdr.exe is open or not, when the code detects that it isn't open i want it to open some other code but i want it to only do it once instead of looping.

Help me understand, the issue here is that after calling your "other code" a.k.a data.vbs while keeps on executing it? Add a break after subprocess.call("cmd /c data.vbs").
Or structure it like this:
while True:
if not checkIfProcessRunning('TDR'):
break
print('TDR (tdr.exe) is running')
# Once we find TDR is dead, we execute our other code
print('TDR (tdr.exe) is not running')
subprocess.call("cmd /c data.vbs") # Executes other code
I hope this helps :D

Related

How to stop a process but not the whole script

I have a CLI program in python that will run files. However, if a program is run that never stops, I want the user to be able to 'kill' that program, but not the whole script. The input for stopping the script could be the push of a certain key on the keyboard, I really have no clue how to do this and I couldn't find any answers here. I am using a os.system process, here is a snippet of my code and an example:
if os.path.isfile('../file'):
cmd = os.path.join(os.getcwd(), '../file')
os.system('{} {}'.format('python', cmd))
print('Process finished')
And file contains the following code:
while True:
print("Do stuff")
Please note that I cannot edit 'file' and I want to be able to stop the os.system process with a key pressed without killing the entire main script.
You can encapsulate your block of code in a while loop that will run when the user enters text, and ends when a user enters an empty string (i.e. pressing the Enter or Return key).
while True:
i = input("Enter text (or Enter to quit): ")
if not i:
break
if os.path.isfile(selectedDir+'/'+file):
cmd = os.path.join(os.getcwd(), selectedDir+'/'+file)
os.system('{} {}'.format('python', cmd))
print('Process finished')
print("Your input:", i)
print("While loop has exited")
Alternatively, you can use try and except to handle an exception, and simply continue your program by using pass without error handling:
try:
if os.path.isfile(selectedDir+'/'+file):
cmd = os.path.join(os.getcwd(), selectedDir+'/'+file)
os.system('{} {}'.format('python', cmd))
print('Process finished')
except Exception:
# Your script will continue
pass
from subprocess import Popen,PIPE
is_running = False
if os.path.isfile('../file'):
cmd = os.path.join(os.getcwd(), '../file')
#os.system('{} {}'.format('python', cmd))
proc = Popen(["python3", "-m", cmd],stdout=PIPE, stderr=PIPE)
is_running = False
while is_running:
try:
output, error = proc.communicate()
except KeyboardError:
is_running = False
#Here if Ctrl+C pressed you can exit the program with next line -> Uncomment
#proc.kill()
#IF you want the script to continue after exiting the program all you have to do is uncomment the PASS in next line
#pass
print('Process finished')
You can modify this to check any Key pressed. I'll tag that info here;
To Check For Specific Keyboard Input
Another answer, an overkill, but will do your job

Python: How to resume the python script as soon as vpn network is up?

I have a python script (xyz.py) that I run through the command prompt. My question is that don't we have any method which helps to resume the python code automatically from where it was lost the VPN connection, without any manual intervention. This will help to avoid monitoring the code frequently. Below is my code but it reads from the start if there is any disconnection. Please suggest.
filename = 'xyz.py'
while True:
p = subprocess.Popen('python '+filename, shell=True).wait()
""" #if your there is an error from running 'xyz.py',
the while loop will be repeated,
otherwise the program will break from the loop"""
if p != 0:
continue
else:
break
If me, time.sleep will be used:
import os
import time
from datetime import datetime
import requests
script = 'xyz.py'
def main():
network_check_url = 'http://8.8.8.8'
while True:
try:
requests.get(network_check_url)
except Exception as e:
print(datetime.now(), e)
time.sleep(1)
else:
print('Network is ok. {datetime.now():%Y-%m-%d_%H:%M:%S}')
os.system(f'python {script}')
return
if __name__ == '__main__':
main()

Creating a Flag file

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...

How to kill a process reliably while testing?

I have a couple of different scripts that require opening a MongoDB instance that go something like this:
mongod = Popen(
["mongod", "--dbpath", '/path/to/db'],
)
#Do some stuff
mongod.terminate()
And this works great when the code I'm executing works, but while I'm tinkering, errors inevitably arise. Then the Mongod instance remains running, and the next time I attempt to run the script, it detects that and doesn't open a new one.
I can terminate the process from the command line, but this is somewhat tedious. Or I can wrap everything in a try loop, but for some of the scripts, I have to do this a bunch, since every function depends on every other one. Is there a more elegant way to force close the process even in the event of an error somewhere else in the code?
EDIT: Did some testing based on tdelaney's comment, it looks like when I run these scripts in Sublime text and en error is generated, the script doesn't actually finish - it hits the error and then waits with the mongod instance open... i think. Once I kill the process in the terminal, sublime text tells me "finished in X seconds with exit code1"
EDIT2: On Kirby's suggestion, tried:
def testing():
mongod = Popen(
["mongod", "--dbpath", '/Users/KBLaptop/computation/db/'],
)
#Stuff that generates error
mongod.terminate()
def cleanup():
for proc in subprocess._active[:]:
try: proc.terminate()
except: pass
atexit.register(cleanup)
testing()
The error in testing() seems to prevent anything from continuing, so the atexit never registers and the process keeps running. Am I missing something obvious?
If you're running under CPython, you can cheat and take advantage of Python's destructors:
class PopenWrapper(object):
def __del__(self):
if self._child_created:
self.terminate()
This is slightly ucky, though. My preference would be to atexit:
import atexit
mongod = Popen(...)
def cleanup():
for proc in subprocess._active[:]:
try: proc.terminate()
except: pass
atexit.register(cleanup)
Still slightly hack-ish, though.
EDIT: Try this:
from subprocess import Popen
import atexit
started = []
def auto_popen(*args, **kw):
p = Popen(*args, **kw)
started.append(p)
return p
def testing():
mongod = auto_popen(['blah blah'], shell=True)
assert 0
#Stuff that generates error
mongod.terminate()
def cleanup():
for proc in started:
if proc.poll() is None:
try: proc.kill()
except: pass
atexit.register(cleanup)
testing()

Checking for an open file with a timed refresh in Python

I'm wondering how I would go about having a function refresh itself every minute, and check if a certain file it open. I don't exactly know how to go about this, but heres an example of what I'm looking for:
def timedcheck():
if thisgame.exe is open:
print("The Program is Open!")
else:
print("The Program is closed!")
*waits 1 minute*
timedcheck()
I would also like the script to refresh the function "def timedcheck():" every minute, so it keeps checking if thisgame.exe is open.
I searched through the site already, all suggestions recommended using "import win32ui", which gives me an error when I do.
To repeat this check every minute:
def timedcheck():
while True:
if is_open("thisgame.exe"):
print("The Program is Open!")
else:
print("The Program is closed!")
sleep(60)
Since it's a .exe file, I assume that by "check if this file is open" you mean "check if thisgame.exe" is running. psutil should be helpful - I haven't tested the below code, so it may need some tweaking, but shows the general principle.
def is_open(proc_name):
import psutil
for process in psutil.process_iter():
if proc_name in process.name:
return True
return False
You can use sleep from the time module with an input of 60 for 1 minute delay between checks. You can open the file temporarily and close it if not needed. An IOError will occur if the file is already opened. Catch the error with an exception and the program will wait for another minute before trying again.
import time
def timedcheck():
try:
f = open('thisgame.exe')
f.close()
print("The Program is Closed!")
except IOError:
print("The Program is Already Open!")
time.sleep(60) #*program waits 1 minute*
timedcheck()
Here's a variation on #rkd91's answer:
import time
thisgame_isrunning = make_is_running("thisgame.exe")
def check():
if thisgame_isrunning():
print("The Program is Open!")
else:
print("The Program is closed!")
while True:
check() # ignore time it takes to run the check itself
time.sleep(60) # may wake up sooner/later than in a minute
where make_is_running():
import psutil # 3rd party module that needs to be installed
def make_is_running(program):
p = [None] # cache running process
def is_running():
if p[0] is None or not p[0].is_running():
# find program in the process list
p[0] = next((p for p in psutil.process_iter()
if p.name == program), None)
return p[0] is not None
return is_running
To install psutil on Windows for Python 2.7, you could run psutil-0.6.1.win32-py2.7.exe.

Categories