How to implement a timing function in Python? - python

I am thinking to implement a function like below:
timeout = 60 second
timer = 0
while (timer not reach timeout):
do somthing
if another thing happened:
reset timer to 0
My question is how to implement the timer stuff? Multiple thread or a particular lib?
I hope the solution is based on the python built-in lib rather than some third-part fancy package.

I don't think you need threads for what you have described.
import time
timeout = 60
timer = time.clock()
while timer + timeout < time.clock():
do somthing
if another thing happened:
timer = time.clock()
Here, you check every iteration.
The only reason you would need a thread is if you wanted to stop in the middle of an iteration if something was taking too long.

I use the following idiom:
from time import time, sleep
timeout = 10 # seconds
start_doing_stuff()
start = time()
while time() - start < timeout:
if done_doing_stuff():
break
print "Timeout not hit. Keep going."
sleep(1) # Don't thrash the processor
else:
print "Timeout elapsed."
# Handle errors, cleanup, etc

Related

Python: can the time library do task: the loop should stop when a certain time passes?

Can the time library help with the task: the loop should stop when a certain time passes? I'm going to write a light game program in Python that should stop after for example 1 minute and output the result.
I can't find information about this function.
The straightforward solution is to run a while-loop with a time-checking boolean expression:
from datetime import datetime, timedelta
end_time = datetime.now() + timedelta(minutes=1)
while end_time >= datetime.now():
print("Your code should be here")
Another more sophisticated approach is to run the program in a separate thread. The thread checks for an event flag to be set in a while loop condition:
import threading
import time
def main_program(stop_event):
while not stop_event.is_set():
print("Your code should be here")
stop_event = threading.Event()
th_main_program = threading.Thread(target=main_program, args=(stop_event,))
th_main_program.start()
time.sleep(60)
stop_event.set()
In the approaches shown above the program execution finishes gracefully but an iteration within the while-loop has to be finished to check the boolean expression. This means the program doesn't exit immediately once the timeout is reached.
To make the main program exit right away once the timeout is reached, we can use daemon thread. Please note that daemon threads are abruptly stopped at shutdown. Their resources may not be released properly:
import threading
import time
def main_program():
while True:
print("Your code should be here")
th_main_program = threading.Thread(target=main_program, daemon=True)
th_main_program.start()
time.sleep(60)
You need to take time at the start and break your loop when the difference between current time and time at the start is more than you want.
import time
start_time = time.time()
while True:
current_time = time.time()
if current_time - start_time > 60: #time in seconds
break
#your code
You can also add time.sleep(0.01) to the loop to limit your fps.

How can I input a time and have the timer count down?

I am trying to run a while loop so I can run code while the timer is still counting down.I also want to see the timer as it counts down. I have tried to find something similar on stack overflow, but haven't been able to get the result I'm looking for.
print("Input minutes and seconds")
min = int(input("Minutes: "))
sec = int(input("Seconds: "))
while min & sec > 0:
# do some code
# I want the program to count down from whatever I input
print("")
You should run your timer on a different thread. If you don't need the timer to affect the main code being run this should work:
import threading
import time
def timer_function(seconds):
'''Countdown from number of seconds given'''
for t in range(seconds, -1, -1):
time.sleep(1)
print(t)
if __name__ == "__main__":
print("Input minutes and seconds")
min = int(input("Minutes: "))
sec = int(input("Seconds: "))
x = threading.Thread(target=timer_function, args=(min * 60 + sec,))
x.start()
# Run some other code in parallel with the timer
x.join() # will wait for the timer function to finish
print('All done')
If you need the timer to stop the main thread (the code being run on the main function) then you need send some signal through a variable from the timer thread.
There might be some libraries that handle thread timeouts better if you would like to look it up :)
Getting very precise timeout timing is somewhat troublesome, as the operation of reporting on the timing can affect the timing itself if not carefully written.
Something like this is often best accomplished with two threads in parallel
Making the threads "daemon threads" allows you to end them by quitting the program (otherwise the program will wait for them to be .join()ed)
You can rely on threading.Event() to clearly communicate into a thread and provide a .wait() method, which will either wait for a given timeout or immediately end when the event .is_set()
import threading
import time
def function_to_call(): # replace me with your function
time.sleep(1000)
def timer_fn(timeout, event, delay=5): # 5 seconds between reports
time_end = time.time() + timeout
while not event.is_set():
time_remaining = int(time_end - time.time())
if time_remaining <= 0:
return
print(f"{int(time_remaining)}s remaining")
event.wait((min(delay, time_remaining))) # wait for event
timeout = int(input("minutes: ") or 0) * 60 + int(input("seconds: ") or 0)
E = threading.Event() # Event to kill t2
# making t1 a daemon lets it not prevent shutdown
t1 = threading.Thread(target=function_to_call, daemon=True)
t2 = threading.Thread(target=timer_fn, args=(timeout, E), daemon=True)
# begin both threads
t1.start()
t2.start()
# wait for t1 to exit (but not t2)
t1.join(timeout=timeout)
# t1 may join faster by ending, otherwise reach here after timeout
E.set() # set the Event to quickly end t2 (timeout or t1 returned)
t2.join() # not technically necessary, but cleans up t2
# program quits and t1 is killed if it's still running
Note that the timing display is actually separate from the thread ending, and ending the function early is done here by stopping the program. The function will continue to run if the program is not stopped!
If more advanced task control is needed, consider
modifying your callable function to repeatedly check another threading.Event throughout it to see if it's time is up (yet)
use multiprocessing, which is much more featureful than threading, though it may need to copy memory into the new process, which can be slow if you have a tremendous amount
use subprocess, creating a script just for the purpose of a timed end (here you can kill the subprocess with a simple .kill() or setting a timeout= argument when creating it! (though again you'll find some inefficiency in copying/streaming input into and out of the new process)
use os.fork() and [os.kill()](https://docs.python.org/3/library/os.html#os.kill) to split your process (advanced, but usually much more efficient than multiprocessing` due to how memory is (or rather is not) copied)
if your function can be made asynchronous, which allows multiple tasks to collaborate in the same namespace similar to threading, but in a more friendly way (though how this behaves is fundamentally different from the other techniques given, it can be very efficient if you have many tasks which don't rely on local resources, such as a webserver or database)
Though further fundamentally different, you may find further or more benefit in designing your task to be a collection of work to iterate over (maybe in a list) and consider a library like tqdm to report on its status
Try this,
Code :
import time
print("Input minutes and seconds")
min = int(input("Minutes: "))
sec = int(input("Seconds: "))
t = min*60 + sec
while t :
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
print(timer, end="\r")
time.sleep(1)
t -= 1
print('Timer ended !!')
Output :
Input minutes and seconds
Minutes: 1
Seconds: 5
01:05
01:04
01:03
01:02
01:01
01:00
00:59
00:58
.
.
.
00:01
Timer ended !!
You should ideally use threads and spawn a daemon to keep track, but that might be overkill for your case. I've made a more simple implementation which is hopefully understandable, otherwise please ask and I'll improve the comments/explanation:
import time
set_time = int(input('For how many seconds do you want to run this?'))
start_time = time.time() # lets get the current time
inner_time = time.time() # Seperate vars so we don't overwrite the main loop
count = 0 #To keep track of how many seconds we've been going
while (time.time() - start_time) < set_time: #Lets run this until we've reached our time
if(time.time() - inner_time) >= 1: #If 1 sec has passed
inner_time = time.time() #Reset time
count += 1 #Increase second by 1
print("Code has been running for "+str(count)+" seconds") #Inform the user
#Do something here...
print(str(set_time)+" seconds have now elapsed") #Done and dusted
This is the output:
For how long do you want to run this?5
Code has been running for 1 seconds
Code has been running for 2 seconds
Code has been running for 3 seconds
Code has been running for 4 seconds
5 seconds have now elapsed

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 do I create a scheduled task using Python Win32com that runs every 5 seconds?

I am trying to create a scheduled task in Python using Win32com. I am able to create a daily trigger. However, I cannot find a way to create a trigger every 5 seconds or every minute for that matter. Does anybody have any pointers on how to do that?
As said in a comment, if you want to do stuff with this frequency you are better off just having your program run forever and do its own scheduling.
In a similar fashion to #Barmak Shemirani's answer, but without spawning threads:
import time
def screenshot():
# do your screenshot...
interval = 5.
target_time = time.monotonic() + interval
while True:
screenshot()
delay = target_time - time.monotonic()
if delay > 0.:
time.sleep(delay)
target_time += interval
or, if your screenshot is fast enough and you don't really care about precise timing:
while True:
screenshot()
time.sleep(interval)
If you want this to run from the system startup, you'll have to make it a service, and change the exit condition accordingly.
pywin32 is not required to create schedule or timer. Use the following:
import threading
def screenshot():
#pywin32 code here
print ("Test")
def starttimer():
threading.Timer(1.0, starttimer).start()
screenshot()
starttimer()
Use pywin32 for taking screenshot etc.

python -> time a while loop has been running

i have a loop that runs for up to a few hours at a time. how could I have it tell me how long it has been at a set interval?
just a generic...question
EDIT: it's a while loop that runs permutations, so can i have it print the time running every 10 seconds?
Instead of checking the time on every loop, you can use a Timer object
import time
from threading import Timer
def timeout_handler(timeout=10):
print time.time()
timer = Timer(timeout, timeout_handler)
timer.start()
timeout_handler()
while True:
print "loop"
time.sleep(1)
As noted, this is a little bit of a nasty hack, as it involves checking the time every iteration. In order for it to work, you need to have tasks that run for a small percentage of the timeout - if your loop only iterates every minute, it won't print out every ten seconds. If you want to be interrupted, you might consider multithreading, or preferably if you are on linux/mac/unix, signals. What is your platform?
import time
timeout = 10
first_time = time.time()
last_time = first_time
while(True):
pass #do something here
new_time = time.time()
if new_time - last_time > timeout:
last_time = new_time
print "Its been %f seconds" % (new_time - first_time)
Output:
Its been 10.016000 seconds
Its been 20.031000 seconds
Its been 30.047000 seconds
There's a very hacky way to do this by using time.asctime(). You store the asctime before entering the while loop and somewhere in the loop itself. Calculate the time difference between the stored time and the current time and if that difference is 10 seconds, then update the stored time to the current time and print that it's been running.
However, that's a very hacky way to do it as it requires some twisted and boring math.
If your aim is to check the runtime of a specific algorithm, then you're better off using the timeit module
Hope this Helps

Categories