Stop opening VLC in python - python

I wrote a little code which scans the wifi signals in the air and according to the amount plays one or another audio file.
import time
import subprocess
import os
while True:
output = subprocess.Popen("airport en1 -s", shell=True, stdout=subprocess.PIPE).stdout.read()
lines = output.split('\n')
n = len(lines)
if n < 10:
print os.path.exists('/Users/shirin/Desktop/wifi/1.mp3')
p = subprocess.Popen(['/Applications/VLC.app/Contents/MacOS/VLC','/Users/shirin/Desktop/wifi/1.mp3'])
elif n > 10:
print os.path.exists('/Users/shirin/Desktop/wifi/1.mp3')
p = subprocess.Popen(['/Applications/VLC.app/Contents/MacOS/VLC','/Users/shirin/Desktop/wifi/1.mp3'])
Now my problem is that, when I run the file through the terminal it keeps running the code over and over again and I do not know how to stop it. It also does not stop when I close the terminal.
So my question:
How can I tell python to run the code once and then stop?
already super thanks!

Two things:
You have a while True: and no condition to break the loop, insert a break after reproducing the audio file so the loop could stop.
Even if you close the program VLC would be running until you manually stop it. This is because you are just calling an external command. If you want to reproduce the audio from python you can use another library like pygame

You can call p.terminate() if you want to terminate your application.
You can also call p.kill() if your application is not responsive.
Now, let's say you want to stop the application and stop VLC.
Have except KeyboardInterrupt: in your code and call p.terminate() when you stop the script.
while True:
try:
... #code goes here.
except KeyboardInterrupt:
p.terminate()

Related

Detecting application start up with python

I've working on a windows python program and I need it to run once I open an app. Is it possible ? If so how would I implement it ?
We need some information, what did you want to do?
Did you wanna know, if a process is started and then you will continue you python script? Than you can do this:
import psutil
def is_process_running(processName):
for process in psutil.process_iter(): # iterates through all processes from your OS
try:
if processName.lower() in process.name().lower(): # lowers the name, because "programm" != proGramm"
return True # if the process is found, then return true
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): # some failures what could go wrong
pass
return False;
while(!is_process_running('nameOfTheProcess') # only continue as long as the return is False
time.sleep(10) # wait 10 seconds
For further information:
psutil-docs
This can be achieved in multiple ways, following can also be the one.
import subprocess
#sub-process library being part of python doesn't
#require any additional installation and can do all the work.
#For Windows operating system we can use 'tasklist'
#in place of 'ps aux' as the first argument
#(haven't work with windows lately but this is close to something i remember).
#check_output api called when shell=true,returns list of running processes.
running_processes = subprocess.check_output(['ps aux'], shell=True)
#check if the application needed is running, for brevity, I am using firefox,
#if yes, it fires off another python script.
if bytes('firefox',encoding='utf-8') in running_processes:
subprocess.call(['python3', '/path/to/application.py'])
else:
print('it not')

Stopping a program in if statement [duplicate]

How do I exit a script early, like the die() command in PHP?
import sys
sys.exit()
details from the sys module documentation:
sys.exit([arg])
Exit from Python. This is implemented by raising the
SystemExit exception, so cleanup actions specified by finally clauses
of try statements are honored, and it is possible to intercept the
exit attempt at an outer level.
The optional argument arg can be an integer giving the exit status
(defaulting to zero), or another type of object. If it is an integer,
zero is considered “successful termination” and any nonzero value is
considered “abnormal termination” by shells and the like. Most systems
require it to be in the range 0-127, and produce undefined results
otherwise. Some systems have a convention for assigning specific
meanings to specific exit codes, but these are generally
underdeveloped; Unix programs generally use 2 for command line syntax
errors and 1 for all other kind of errors. If another type of object
is passed, None is equivalent to passing zero, and any other object is
printed to stderr and results in an exit code of 1. In particular,
sys.exit("some error message") is a quick way to exit a program when
an error occurs.
Since exit() ultimately “only” raises an exception, it will only exit
the process when called from the main thread, and the exception is not
intercepted.
Note that this is the 'nice' way to exit. #glyphtwistedmatrix below points out that if you want a 'hard exit', you can use os._exit(*errorcode*), though it's likely os-specific to some extent (it might not take an errorcode under windows, for example), and it definitely is less friendly since it doesn't let the interpreter do any cleanup before the process dies. On the other hand, it does kill the entire process, including all running threads, while sys.exit() (as it says in the docs) only exits if called from the main thread, with no other threads running.
A simple way to terminate a Python script early is to use the built-in quit() function. There is no need to import any library, and it is efficient and simple.
Example:
#do stuff
if this == that:
quit()
Another way is:
raise SystemExit
You can also use simply exit().
Keep in mind that sys.exit(), exit(), quit(), and os._exit(0) kill the Python interpreter. Therefore, if it appears in a script called from another script by execfile(), it stops execution of both scripts.
See "Stop execution of a script called with execfile" to avoid this.
While you should generally prefer sys.exit because it is more "friendly" to other code, all it actually does is raise an exception.
If you are sure that you need to exit a process immediately, and you might be inside of some exception handler which would catch SystemExit, there is another function - os._exit - which terminates immediately at the C level and does not perform any of the normal tear-down of the interpreter; for example, hooks registered with the "atexit" module are not executed.
I've just found out that when writing a multithreadded app, raise SystemExit and sys.exit() both kills only the running thread. On the other hand, os._exit() exits the whole process. This was discussed in "Why does sys.exit() not exit when called inside a thread in Python?".
The example below has 2 threads. Kenny and Cartman. Cartman is supposed to live forever, but Kenny is called recursively and should die after 3 seconds. (recursive calling is not the best way, but I had other reasons)
If we also want Cartman to die when Kenny dies, Kenny should go away with os._exit, otherwise, only Kenny will die and Cartman will live forever.
import threading
import time
import sys
import os
def kenny(num=0):
if num > 3:
# print("Kenny dies now...")
# raise SystemExit #Kenny will die, but Cartman will live forever
# sys.exit(1) #Same as above
print("Kenny dies and also kills Cartman!")
os._exit(1)
while True:
print("Kenny lives: {0}".format(num))
time.sleep(1)
num += 1
kenny(num)
def cartman():
i = 0
while True:
print("Cartman lives: {0}".format(i))
i += 1
time.sleep(1)
if __name__ == '__main__':
daemon_kenny = threading.Thread(name='kenny', target=kenny)
daemon_cartman = threading.Thread(name='cartman', target=cartman)
daemon_kenny.setDaemon(True)
daemon_cartman.setDaemon(True)
daemon_kenny.start()
daemon_cartman.start()
daemon_kenny.join()
daemon_cartman.join()
from sys import exit
exit()
As a parameter you can pass an exit code, which will be returned to OS. Default is 0.
I'm a total novice but surely this is cleaner and more controlled
def main():
try:
Answer = 1/0
print Answer
except:
print 'Program terminated'
return
print 'You wont see this'
if __name__ == '__main__':
main()
...
Program terminated
than
import sys
def main():
try:
Answer = 1/0
print Answer
except:
print 'Program terminated'
sys.exit()
print 'You wont see this'
if __name__ == '__main__':
main()
...
Program terminated Traceback (most recent call last): File "Z:\Directory\testdieprogram.py", line 12, in
main() File "Z:\Directory\testdieprogram.py", line 8, in main
sys.exit() SystemExit
Edit
The point being that the program ends smoothly and peacefully, rather than "I'VE STOPPED !!!!"
Problem
In my practice, there was even a case when it was necessary to kill an entire multiprocessor application from one of those processes.
The following functions work well if your application uses the only main process. But no one of the following functions didn't work in my case as the application had many other alive processes.
quit()
exit(0)
os._exit(0)
sys.exit(0)
os.kill(os.getppid(), 9) - where os.getppid() is the pid of parent process
The last one killed the main process and itself but the rest processes were still alive.
Solution
I had to kill it by external command and finally found the solution using pkill.
import os
# This can be called even in process worker and will kill
# whole application included correlated processes as well
os.system(f"pkill -f {os.path.basename(__file__)}")
In Python 3.5, I tried to incorporate similar code without use of modules (e.g. sys, Biopy) other than what's built-in to stop the script and print an error message to my users. Here's my example:
## My example:
if "ATG" in my_DNA:
## <Do something & proceed...>
else:
print("Start codon is missing! Check your DNA sequence!")
exit() ## as most folks said above
Later on, I found it is more succinct to just throw an error:
## My example revised:
if "ATG" in my_DNA:
## <Do something & proceed...>
else:
raise ValueError("Start codon is missing! Check your DNA sequence!")
My two cents.
Python 3.8.1, Windows 10, 64-bit.
sys.exit() does not work directly for me.
I have several nexted loops.
First I declare a boolean variable, which I call immediateExit.
So, in the beginning of the program code I write:
immediateExit = False
Then, starting from the most inner (nested) loop exception, I write:
immediateExit = True
sys.exit('CSV file corrupted 0.')
Then I go into the immediate continuation of the outer loop, and before anything else being executed by the code, I write:
if immediateExit:
sys.exit('CSV file corrupted 1.')
Depending on the complexity, sometimes the above statement needs to be repeated also in except sections, etc.
if immediateExit:
sys.exit('CSV file corrupted 1.5.')
The custom message is for my personal debugging, as well, as the numbers are for the same purpose - to see where the script really exits.
'CSV file corrupted 1.5.'
In my particular case I am processing a CSV file, which I do not want the software to touch, if the software detects it is corrupted. Therefore for me it is very important to exit the whole Python script immediately after detecting the possible corruption.
And following the gradual sys.exit-ing from all the loops I manage to do it.
Full code: (some changes were needed because it is proprietory code for internal tasks):
immediateExit = False
start_date = '1994.01.01'
end_date = '1994.01.04'
resumedDate = end_date
end_date_in_working_days = False
while not end_date_in_working_days:
try:
end_day_position = working_days.index(end_date)
end_date_in_working_days = True
except ValueError: # try statement from end_date in workdays check
print(current_date_and_time())
end_date = input('>> {} is not in the list of working days. Change the date (YYYY.MM.DD): '.format(end_date))
print('New end date: ', end_date, '\n')
continue
csv_filename = 'test.csv'
csv_headers = 'date,rate,brand\n' # not real headers, this is just for example
try:
with open(csv_filename, 'r') as file:
print('***\nOld file {} found. Resuming the file by re-processing the last date lines.\nThey shall be deleted and re-processed.\n***\n'.format(csv_filename))
last_line = file.readlines()[-1]
start_date = last_line.split(',')[0] # assigning the start date to be the last like date.
resumedDate = start_date
if last_line == csv_headers:
pass
elif start_date not in working_days:
print('***\n\n{} file might be corrupted. Erase or edit the file to continue.\n***'.format(csv_filename))
immediateExit = True
sys.exit('CSV file corrupted 0.')
else:
start_date = last_line.split(',')[0] # assigning the start date to be the last like date.
print('\nLast date:', start_date)
file.seek(0) # setting the cursor at the beginnning of the file
lines = file.readlines() # reading the file contents into a list
count = 0 # nr. of lines with last date
for line in lines: #cycling through the lines of the file
if line.split(',')[0] == start_date: # cycle for counting the lines with last date in it.
count = count + 1
if immediateExit:
sys.exit('CSV file corrupted 1.')
for iter in range(count): # removing the lines with last date
lines.pop()
print('\n{} lines removed from date: {} in {} file'.format(count, start_date, csv_filename))
if immediateExit:
sys.exit('CSV file corrupted 1.2.')
with open(csv_filename, 'w') as file:
print('\nFile', csv_filename, 'open for writing')
file.writelines(lines)
print('\nRemoving', count, 'lines from', csv_filename)
fileExists = True
except:
if immediateExit:
sys.exit('CSV file corrupted 1.5.')
with open(csv_filename, 'w') as file:
file.write(csv_headers)
fileExists = False
if immediateExit:
sys.exit('CSV file corrupted 2.')
In Python 3.9, you can also use: raise SystemExit("Because I said so").
Just put at the end of your code quit() and that should close a python script.
use exit and quit in .py files
and sys.exit for exe files

Print line by line when running a process in python?

I recently worked on using multithreading but ran into an issue where it seems that multiprocessing would be the better way to go. When I run a simple loop counter function as a process, why doesn't it iterate through the loop and print out the output? Instead the code waits for a set amount of time before producing the output. Is there a way this can be solved or am I stuck dealing with processes this way?
import multiprocessing, time
def loop_process(process_name):
loopCnt = 0
print "\nstarting {}".format(process_name)
for loopCnt in range(15):
print("value of loopCnt = {}".format(loopCnt))
loopCnt += 1
time.sleep(1)
print('stopping {}'.format(process_name))
if __name__ == '__main__':
L00P_process = multiprocessing.Process(target=loop_process, args=('L00P_process',))
L00P_process.start()
L00P_process.join()
print('processes stopped')
print "Exiting Main"
I'm not clear on what you're seeing. On a Windows box just now, running the program from an interactive console ("DOS box"), I saw value of loopCnt = ... once per second until the program ended. That's what I expected.
Which OS are you running under, how are you running the program, and what exactly are you seeing?
On most (all?) machines, standard output (stdout) is line-buffered if it's attached to an interactive terminal. Which means output is forced to display each time a line boundary is hit. For other kinds of output device, it may use other kinds of buffering, and that could account for a delay.
Something to try: first add
import sys
near the top, then add
sys.stdout.flush()
after your
print("value of loopCnt = {}".format(loopCnt))
That should tell us whether you are, or are not, experiencing a problem with output buffering.

Ending an infinite while loop

I currently have code that basically runs an infinite while loop to collect data from users. Constantly updating dictionaries/lists based on the contents of a text file. For reference:
while (True):
IDs2=UpdatePoints(value,IDs2)
time.sleep(10)
Basically, my problem is that I do not know when I want this to end, but after this while loop runs I want to use the information collected, not lose it by crashing my program. Is there a simple, elegant way to simply exit out of the while loop whenever I want? Something like pressing a certain key on my keyboard would be awesome.
You can try wrapping that code in a try/except block, because keyboard interrupts are just exceptions:
try:
while True:
IDs2=UpdatePoints(value,IDs2)
time.sleep(10)
except KeyboardInterrupt:
print('interrupted!')
Then you can exit the loop with CTRL-C.
You could use exceptions. But you only should use exceptions for stuff that isn't supposed to happen. So not for this.
That is why I recommand signals:
import sys, signal
def signal_handler(signal, frame):
print("\nprogram exiting gracefully")
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
you should put this on the beginning of your program and when you press ctrl+c wherever in your program it will shut down gracefully
Code explanation:
You import sys and signals.
Then you make a function that executes on exit. sys.exit(0) stops the programming with exit code 0 (the code that says, everything went good).
When the program get the SIGINT either by ctrl-c or by a kill command in the terminal you program will shutdown gracefully.
I think the easiest solution would be to catch the KeyboardInterrupt when the interrupt key is pressed, and use that to determine when to stop the loop.
except KeyboardInterrupt:
break
The disadvantage of looking for this exception is that it may prevent the user from terminating the program while the loop is still running.
I use python to track stock prices and submit automated buy/sell commands on my portfolio. Long story short, I wanted my tracking program to ping the data server for info, and place trades off of the information gathered, but I also wanted to save the stock data for future reference, on top of being able to start/stop the program whenever I wanted.
What ended up working for me was the following:
trigger = True
while trigger == True:
try:
(tracking program and purchasing program conditions here)
except:
trigger = False
print('shutdown initialized')
df = pd.DataFrame...
save all the datas
print('shutdown complete')
etc.
From here, while the program is in the forever loop spamming away requests for data from my broker's API, using the CTRL-C keyboard interrupt function toggles the exception to the try loop, which nullifies the while loop, allowing the script to finalize the data saving protocol without bringing the entire script to an abrupt halt.
Hope this helps!
Resultant
I would suggest using the try, except syntax within a loop if you are running on an IPYNB file in Google Colab or Jupyter, like:
while True:
try:
IDs2=UpdatePoints(value,IDs2)
time.sleep(10)
except KeyboardInterrupt:
break
except:
continue
the last except is for any other error if occurs the loop will resume
You can catch the KeyboardInterrupt error in Python:
try:
while 1>0:
IDs2=UpdatePoints(value,IDs2)
time.sleep(10)
except KeyboardInterrupt:
print('While loop ended!')
Also, instead of saying:
while True:
It looks more professional to use:
while 1>0:
To read more about Python Error handling (try, except, etc.):
https://www.w3schools.com/python/python_try_except.asp
or:
https://www.w3schools.com/python/gloss_python_try_finally.asp

How to interrupt a program while it's running?

I wrote a program that reads a text file and runs an .exe for every line in the text file. This results in opening a new command line window for every time i run the .exe. The windows do close on their own once the current task is finished, but the problem is as follows:
If i have 100 lines in the text file, this means that i call the .exe file 100 times. My problem with that is if i want to cancel the run after it already started, i have to click on the red "X" to close every window one after the another.
What i am trying to do is have some sort of a command interrupt the running program and either close all upcoming windows or just stop the for loop from running.
Is it possible to write into the console a command to interrupt the current running code?
Would it be better to use some sort of a key event listener? If so, are there any built-in key listeners in Python? I can't seem to find any. Does that mean that i have to install Pygame just so i can use a key event listener?
Maybe i should try to listen to the command line and detect an exit code on one of the windows that i manually close and that way end the for loop?
There are a few ways you could go about this. But pretty much you have one main issue - you need some sort of flag that can be switched such that the code will know it must stop. For instance, if the code is working in a while-loop, it should check at the start of this loop if the flag is valid, or if the flag is telling the loop to stop...
while flag:
# do code
There are a few ways to implement this flagging like operation for your needs. I will discuss the threading option. First, you need to understand how threading works, and then you need to mold your script such that instead of "running an executable" for each line of the text file, you would read the text file, and put all the lines into a queue, then you would have a few threads that read from that queue, and perform the desired action (like running an executable) but instead of running an external executable, you should mimick this with Python, this thread should be a daemon thread.. and it should have a main loop which checks if a flag that exists in the parent thread is turned on...
Below is an example:
from threading import Thread
from Queue import Queue
import sys
import time
class Performer():
def __init__(self):
self.active = False
self.queue = Queue()
def action(self, line):
pass # your code should be here
def operate(self, text_file, threads=5):
with open(text_file) as f:
for line in f:
self.queue.put(line)
self.active = True
thread_pool = []
for i in range(threads):
t = Thread(target=self.__thread, name=('worker-%d' % i))
t.daemon = True
t.start()
thread_pool.append(t)
while self.active:
try:
if self.queue.empty():
break
except KeyboardInterrupt:
self.active = False
sys.exit('user + keyboard = byebye')
else:
time.sleep(1)
def __thread(self):
while self.active:
if not self.queue.empty():
try:
self.action(self.queue.get())
except Exception:
pass # do something here

Categories

Resources