I have some issues with time.sleep() management in Python. I would like to use some values in a second part of the script, but they have to be delayed 300 ms one from another and I want to delay only that part of the script and not all the rest. These values are the X coordinates of an object detected by a camera. The script is something like this:
while True:
if condition is True:
print(xvalues)
time.sleep(0.3)
if another_condition is True:
#do other stuff and:
np.savetxt('Xvalues.txt', xvalues)
In the second part of the script (#do other stuff), I will write G-code lines with the X-coordinate detected and send them to a CNC machine. If I write a time.sleep() in that position of the script, everything in the while loop will be delayed.
How can I extract some values sampled 300ms a time without influencing the rest of the script?
from threading import Thread
class sleeper(Thread):
if condition is True:
print(xvalues)
time.sleep(0.3)
class worker(Thread):
if another_condition is True:
#do other stuff and:
np.savetxt('Xvalues.txt', xvalues)
def run():
sleeper().start()
worker().start()
You can include the 300ms checking as part of handling condition.
The first time you detect condition, get and remember the current time in a variable.
The next time condition is true again, check that it's more than 300ms from the last time the condition was true.
Something like this:
last_condition_time=None
while True:
if condition is True:
if not last_condition_time or more_than_300ms_ago(last_condition_time):
print(xvalues)
last_condition_time = get_current_time()
if another_condition is True:
#do other stuff and:
np.savetxt('Xvalues.txt', xvalues)
Related
I would like to exit a function by pressing a button using the return statement in the if statement. To write these lines again and again and again is not really what I like. That's why I am basically looking for a function that tells the parent function to return.
Obviously I can't use the return statement in a function and just execute the function where I want to check the variable, although that would be the nicest way I could imagine.
I want to explain it in a loop, but please keep in mind that's not where I want to use it. The usage is for automated processes which should have many exit points.
import keyboard, time
RedFlag = False
def set_RedFlag():
global RedFlag
RedFlag = True
keyboard.add_hotkey("end", set_RedFlag)
PauseFlag = False
def set_PauseFlag():
global PauseFlag
print(PauseFlag)
if PauseFlag == False:
PauseFlag = True
else:
PauseFlag = False
keyboard.add_hotkey("space", set_PauseFlag)
def task():
for i in range(30):
print("test",i)
time.sleep(1)
# Flags
if RedFlag == True: # exitpoint
return
while PauseFlag == True: # pause the script
time.sleep(1/6)
task()
Really relevant is the if statement after #Flags. Especially with the while statement I would have to repeat multiple lines. I would love to have this in one single word as if it was a function.
Edit:
More about the "what for?":
I would like to run a macro and later maybe other tasks. For example writing the odd numbers from 1 to 511. And I want to be able to stop or pause it at any given time.
I forgot to mention, that I tried using the multiprocessing module, since I could terminate the task there. Sadly it is not an option for me not only because the starting time of a process is a bit too long for me, also I am learning a bit about kivy and I know it get's complicated when I want to start another process while using kivy.
I currently have a program that I am working on that requires the user to input some parameters, and then press a button to start the main part of the program.
After the start button is pressed, the if loop executes a sequential order of commands (around 20) and then stops.
I want to be able to stop this sequence of commands at any time during the code using a separate 'stop' button, but I am not sure how. I am more interested in a method of doing this than GUI syntax.
Any help is appreciated.
Example code:
if (start_button_is_pressed):
#do thing a
#do thing b
#do thing c
...
#do thing z
# i want to be able to stop from any point a-z
You can use a loop and break execution at any point. If you want only a single pass through the steps, add a final break at the end.
jump_out = False
while not jump_out:
step_1()
if (jump_out):
break
step_2()
if (jump_out):
break
# and so on
step_n()
break # add unconditional break for single-pass execution
you can use a break statement inside the loop. Set an event such that when the stop button is pressed, it triggers a certain value and this value alters the loop. Sample process below
stop = False
if stop_button_is_pressed:
stop = True
for a in b:
if stop == True:
break
print(a)
print("Stopped")
You could use multiprocessing.Process to terminate() the process/function my_process_function() whenever you please... Run it as script to get outputs.
import multiprocessing
def my_process_function():
for i in range (100):
print(i)
time.sleep(1)
print("my_process end")
if __name__ == "__main__":
x = multiprocessing.Process(target=my_process_function())
x.start()
print("Stop thread?")
a=input()
if (a=="y"):
x.terminate()
I am trying to run 2 functions at different times, one after another.
The first function contains while loop in it (without break, since I want to keep it running until the next function comes)
However, when the next schedule comes, it doesn't run the second function and stuck in the 1st one.
I have tried to add sys.exit() but it doesn't even go into that function
import schedule
import sys
import time
def do_complete_automation():
while True:
print()
print("do_complete_automation()")
time.sleep(5)
def exit1():
print("exit")
sys.exit()
schedule.every().sunday.at('16:42').do(do_complete_automation)
schedule.every().sunday.at('16:42:30').do(exit1)
schedule.every().sunday.at('16:42:35').do(do_complete_automation)
while True:
schedule.run_pending()
time.sleep(1)
It should print "exit"
What is the best way to quickly exit a Python program with an infinite loop that uses curses module?
I've tried adding nodelay() method coupled with this at the end of the loop:
if screen.getch() == ord('q'):
break
However, it takes 2-3 seconds to make all the function calls on one iteration of the loop. And because of the application, it doesn't make sense to run the loop more often than every 5 second. This means that in order for my way of exiting the program to work, I sometimes have to press and hold 'q' for 2-8 seconds.
My code looks like this:
import curses
import time
def main(screen):
refresh_rate = 5
screen.nodelay(1)
# Infinite loop. Displays information and updates it
# every (refresh_rate) # of seconds
while True:
# Makes several http requests
# and passes responses through multiple functions
# Escape infinite loop
if screen.getch() == ord('q'):
break
# Wait before going through the loop again
time.sleep(refresh_rate)
if __name__ == "__main__":
curses.wrapper(main)
My other solution was to replace while True with:
loop = 1
while loop:
#Loop code
if screen.getch() == ord('q'):
loop = -1
This way, there is no need to press and hold 'q' to exit the program. But it can still take up to 8 seconds to exit after pressing 'q' once.
For obvious reasons, this doesn't seem to be the best way of exiting the program. I am pretty sure there should be a better (faster) solution.
Other than that, the program works fine. It's 2 files with more than 300 lines, so I am posting just the relevant parts of the code with my attempted solutions.
Given that you have nodelay already, the usual approach is to use napms with a small (20-50 milliseconds) time, and addressing your 5-seconds goal, to run the functions after several (10-25) repetitions of the getch/napms loop.
Mixing curses and standard I/O doesn't really work well unless you take care to flush things when switching between the two.
What's probably happening is that your 'q' is coming in between the getch() and the sleep calls. Given that getch() takes a fraction of a second to execute and sleep locks the program for 5 seconds, it's very likely that any time you press a key you're going to wait.
The easiest way to exit any python script is to press Ctrl-C - it spawns a KeyBoardInterrupt exception that can be handled like:
try:
while True:
do_something()
except KeyboardInterrupt:
pass
Granted, if this is meant to be a user-facing application, that might not be sufficient. But it's also unlikely that any production application would operate without a full event loop and a UI that would allow them to exit.
Last, if you want another way of doing what you're already doing, you can use:
import sys
sys.stdin.read(1)
To read 1 bye of user input at a time. I'd go for the Ctrl-C route, if I were you.
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