Python thread - run every X minutes unless last thread is still running - python

This is for a 3.x python program. One thread is created for a web server - no problems there.
There is another function running in a thread that I would like to run every X seconds unless the prior thread is still running in which case we can skip this iteration. I'm not looking for a break of X seconds between the end of the prior run and the start of a new one.
Desired behavior:
X = 180 seconds (3 minutes)
8:00 am - Code begins
8:01 am - Code completes
8:03 am - Code begins
8:07 am - Code completes (we skipped the 8:06 am run)
8:09 am - Code begins
The following code runs the function (main) every X seconds, but doesn't check to see if there is already a prior thread running.
def sync():
t_sync = threading.Timer(syncInterval, sync)
t_sync.daemon = False
t_sync.start()
main()
What's the best way to accomplish this?
Thanks to PygoNode's idea about is_alive() I was able to get the following working. This probably isn't the most elegant way to do this, but it works.
def sync():
t_sync = threading.Thread(target=main)
t_sync.daemon = False
t_sync.start()
while True:
time.sleep (syncInterval)
if t_sync.is_alive():
logger.warning ('Sync: Prior thread still running. Do not kick off another sync.')
else:
t_sync = threading.Thread(target=main)
t_sync.daemon = False
t_sync.start()

threading.Timer has a is_alive() method. You could refactor your sync() method to return the thread after starting, and then pass that reference to your next sync() call check if the existing is still alive/running.

Related

How to kill the process after particular timeout in python?

I am having a python function that has loop which may fall into infinte loop.
I want to kill the function and print error if it exceeds the time limit let's say 10 sec.
For eg. this is the function that contains infinite loop
def myfunc(data):
while True:
data[0]+=10
return data
data=[57,6,879,79,79,]
On calling from here
print(myfunc(data))
I want it to completely kill the process and print the message. I am working on windows.
Any reference or resource will be helpful.
Thanks
Maybe you can try with func-timeout Python package.
You can install it with the following command:
pip install func-timeout
This code will resolve your problem "I want to kill the function and print error if it exceeds the time limit let's say 10 sec."
from time import process_time as timer
def whatever(function):
start = timer()
infinite loop here:
end = timer()
(your code here)
if end >= 10:
print(whatever)
return
Breakdown: there are a few options for doing this with the time module
At the start of your program import the method
At the beginning of your (infinite loop) start = timer() will call process_time and save the value as start.
end = timer() will continue to send the call to process_time storing new value
put w/e code you want in your loop
if end >= 10: will keep checking the count each loop iteration
print(whatever)
return will automatically terminate the function by escaping if time runs 10 seconds when it is checked next loop.
This doesn't say "how to stop the process_time" from running once its called idk if it continues to run in the background and you have to stop it on your on. But this should answer your question. And you can investigate a bit further with what I've given you.
note: This is not designed to generate "precision" timing for that a more complex method will need to be found

How to run a python script multiple times simultaneously using python and terminate all when one has finished

Maybe it's a very simple question, but I'm new in concurrency. I want to do a python script to run foo.py 10 times simultaneously with a time limit of 60 sec before automatically abort. The script is a non deterministic algorithm, hence all executions takes different times and one will be finished before the others. Once the first ends, I would like to save the execution time, the output of the algorithm and after that kill the rest of the processes.
I have seen this question run multiple instances of python script simultaneously and it looks very similar, but how can I add time limit and the possibility of when the first one finishes the execution, kills the rest of processes?
Thank you in advance.
I'd suggest using the threading lib, because with it you can set threads to daemon threads so that if the main thread exits for whatever reason the other threads are killed. Here's a small example:
#Import the libs...
import threading, time
#Global variables... (List of results.)
results=[]
#The subprocess you want to run several times simultaneously...
def run():
#We declare results as a global variable.
global results
#Do stuff...
results.append("Hello World! These are my results!")
n=int(input("Welcome user, how much times should I execute run()? "))
#We run the thread n times.
for _ in range(n):
#Define the thread.
t=threading.Thread(target=run)
#Set the thread to daemon, this means that if the main process exits the threads will be killed.
t.setDaemon(True)
#Start the thread.
t.start()
#Once the threads have started we can execute tha main code.
#We set a timer...
startTime=time.time()
while True:
#If the timer reaches 60 s we exit from the program.
if time.time()-startTime>=60:
print("[ERROR] The script took too long to run!")
exit()
#Do stuff on your main thread, if the stuff is complete you can break from the while loop as well.
results.append("Main result.")
break
#When we break from the while loop we print the output.
print("Here are the results: ")
for i in results:
print(f"-{i}")
This example should solve your problem, but if you wanted to use blocking commands on the main thread the timer would fail, so you'd need to tweak this code a bit. If you wanted to do that move the code from the main thread's loop to a new function (for example def main(): and execute the rest of the threads from a primary thread on main. This example may help you:
def run():
pass
#Secondary "main" thread.
def main():
#Start the rest of the threads ( in this case I just start 1).
localT=threading.Thread(target=run)
localT.setDaemon(True)
localT.start()
#Do stuff.
pass
#Actual main thread...
t=threading.Thread(target=main)
t.setDaemon(True)
t.start()
#Set up a timer and fetch the results you need with a global list or any other method...
pass
Now, you should avoid global variables at all costs as sometimes they may be a bit buggy, but for some reason the threading lib doesn't allow you to return values from threads, at least i don't know any methods. I think there are other multi-processing libs out there that do let you return values, but I don't know anything about them so I can't explain you anything. Anyways, I hope that this works for you.
-Update: Ok, I was busy writing the code and I didn't read the comments in the post, sorry. You can still use this method but instead of writing code inside the threads, execute another script. You could either import it as a module or actually run it as a script, here's a question that may help you with that:
How to run one python file in another file?

code not keep going after thread

I wrote this code to lock a mouse in the middle of the screen
def lockmouse():
print "here"
while True:
win32api.SetCursorPos((GetSystemMetrics(0)/2,GetSystemMetrics(1)/2))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,GetSystemMetrics(0)/2,GetSystemMetrics(1)/2,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,GetSystemMetrics(0)/2,GetSystemMetrics(1)/2,0,0)
t = threading.Thread(target=lockmouse())
command = "lockmouse"
if "lockmouse" in command:
if t.is_alive==False:
t.start()
time.sleep(3)
t._Thread_stop()
and its not keep going after the t.start().I've been trying using different methods to stop the thread,but its even not make it after that line.anyone know what the problem?
It might be the fact that your function isn't indented properly. It should be:
def foo():
return 'bar'
Also, you seem to only be starting a single thread. What's the point?
EDIT:
I just realised that your function has an infinite loop. The program cannot carry on from t.start() because it has to wait for that function to finish execution, which it won't because there's a while loop. You either need to restructure your program somehow, or if you want to keep it how it is, see this answer for how to avoid waiting for a thread.
How to avoid waiting for a thread to finish execution - Python

How Do I Loop An Input In Python?

I have been searching and searching on how to figure out how to make an input or something go into a while loop. As in, the input() command won't stop my stopwatch. I have tried tkinter, pygame, and a couple other methods, but they just didn't work. If anyone can help me out, I would prefer something small and simple, if that's even possible. And to be specific on what I want to learn to do, is basically allowing, when any key is pressed, for it to instantly stop (preferably without hitting enter). Thanks, saddlepiggy!
Here is what I have so far, with nothing to activate the stopping:
#Setup (Variables and stuff)
hours = 0
minutes = 0
seconds = 0
import time
#Main Part of Code
print("Welcome to PyWatch, a stopwatch coded in Python!")
print("Press any key to start the stopwatch.")
print("Then, press any key to stop it!")
start = input("")
while hours < 48:
seconds = seconds + 1
time.sleep(1)
print(hours, "hours,", minutes, "minutes,", seconds, "seconds")
#If Statements for getting seconds/minutes/hours
if (seconds == 60):
minutes = minutes + 1
seconds = seconds - 60
if (minutes == 60):
hours =hours + 1
minutes = minutes - 60
Threading is what you want.
Create a second thread that waits for the input while your first thread handles your stopwatch code. Behold:
import threading, sys
def halt():
raw_input()
threading.Thread(target=halt).start()
while hours < 48 and threading.active_count() > 1:
seconds = seconds + 1
time.sleep(1)
# copy and past what you had before
Allow me to elaborate on what's happening: Thus far, all of the code you've written has been single threaded. This means only one line of code is executed at a time, there's only one thread of execution. Consequentially, your script can't multitask, it can't wait for input and print the time at the same time.
So when this line is evaluated
threading.Thread(target=halt).start()
The main thread creates a second thread of execution. Meanwhile, the main thread goes on and enters the while loop. The target parameter is the entry point of the thread, it's the starting point. It's analogous to if __name__ == "__main__:" for the main thread. Just as the main thread terminates when it reaches the end of if __name__ == "__main__:", our second thread will terminate once it reaches the end of halt().
The threading.active_count function tells you how many threads in are current in execution.
You can't do that in Python. You are asking for a keyboard event. Keyboard events are shipped with a GUI. This thread explains pretty much everything: QKeyPress event in PyQt
Or use an external application for your OS that can append output to a file that is read by your Python program in a loop. When a certain event is detected you can perform some actions. For Linux this tread explains: https://superuser.com/questions/248517/show-keys-pressed-in-linux

How to find running time of a thread in Python

I have a multi-threaded SMTP server. Each thread takes care of one client. I need to set a timeout value of 10 seconds on each server thread to terminate dormant or misbehaving clients.
I have used the time.time(), to find the start time and my checkpoint time and the difference gives the running time. But I believe it gives the system time and not the time this thread was running.
Is there a Thread local timer API in Python ?
import threading
stop = 0
def hello():
stop = 1
t=threading.Timer(10,hello)
t.start()
while stop != 1:
print stop
print "stop changed"
This prints 0 (initial stop) in a loop and does not come out of the while loop.
Python has progressed in the 6 years since this question was asked, and in version 3.3 it's introduced a tool for exactly what was being asked for here:
time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID)
Python 3.7 additionally introduced an analogous time.clock_gettime_ns.
Detailed docs are exactly where you'd expect but the feature is pretty straightforward straight out of the box.
In the python documentation there is no mention of "thread timing". Either the clocks are process-wide or system-wide. In particular time.clock measures process time while time.time returns the system time.
In python3.3 the timings API was revised and improved but still, I can't see any timer that would return the process time taken by a single thread.
Also note that even if possible it's not at all easy to write such a timer.
Timers are OS specific, so you would have to write a different version of the module for every OS. If you want to profile a specific action, just launch it without threads.
When threaded the timing either it runs as expected, or it is a lot slower because of the OS, in which case you can't do nothing about it(at least, if you don't want to write a patch that "fixes" the GIL or removes it safely).
Python 3.7 has added the time.thread_time() method that seems to do what this question needs. According to the docs, it is thread-specific and excludes time spent sleeping.
The hello function's stop value is local, not the global one.
Add the following:
def hello():
global stop
stop = 1
I am posting a sample code which can measure the running time of the thread, you can modify the code, so as to use with your function.
import time
import threading
def hello():
x = 0
while x < 100000000:
pass
x += 1
start = time.clock()
t = threading.Thread(target = hello, args = ())
t.start()
t.join()
end = time.clock()
print "The time was {}".format(end - start)
On my system, it gave a time of 8.34 seconds.

Categories