python -> time a while loop has been running - python

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

Related

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

Sleeping for the remaining time

I'm trying to run a method every minute.
The method does some operations on the internet so it might take anywhere from 1 second to 30 seconds.
What I want to do is calculate the time spent by this method and then sleep for the remaining time, to make sure that the method itself runs every minute.
Currently my code looks like this:
def do_operation():
access_db()
sleep(60)
As you can see this does not take into account the delay whatsoever, and although it works, it will at some point fail and skip a minute completely, which should never happen.
import time
def do_operation():
start = time.time()
access_db()
time.sleep(60-time.time()+start)
This code will allow you to run a callable in defined intervals:
import time
import random
def recurring(interval, callable):
i = 0
start = time.time()
while True:
i += 1
callable()
remaining_delay = max(start + (i * interval) - time.time(), 0)
time.sleep(remaining_delay)
def tick_delay():
print('tick start')
time.sleep(random.randrange(1, 4))
print('tick end')
recurring(5, tick_delay)
Notes
The function tick_delay sleeps for some seconds to simulate a function which can take an undefined amount of time.
If the callable takes longer than the defined loop interval, the next iteration will be scheduled immediately after the last ended. To have the callable run in parallel you need to use threading or asyncio

Python command to run on every 45th second

How do i make the the program run every time the timestamp in seconds is 45, currently I am using time.sleep, but my run time tends to vary a little bit every time the program is executed and i would like it to execute again if the timestamp is on the 45th second. Currently I have something like this where the run loop commences every 60 seconds, however I would like it to run the loop when the timestamp seconds slot == 45
def run_loop(self):
while True:
sys.stdout.write("-----\n")
sys.stdout.flush()
start = time.time()
self.takeProfit()
self.place_orders()
end = time.time()
print("runtime is ", end - start)
sleep(60)
def run():
# Try/except just keeps ctrl-c from printing an ugly stacktrace
ei = ExchangeInterface()
try:
ei.run_loop()
except (KeyboardInterrupt, SystemExit):
sys.exit()
ExchangeInterface.run()
My run time at the moment tends to be around 18-20 seconds
You could use the datetime module, and check if datetime.now().second == 45.
E.g.
from datetime import datetime
if datetime.now().second == 45:
do_stuff()
In your case you would use some logic to check every X amount of time if we are at the 45th second.
So I assume you specifically mean run an event at the 45-th second of the minute?
That sounds like you want to do event scheduling:
https://docs.python.org/3/library/sched.html
In the example on that page, they only use the enter method of the scheduler and not enterabs, which is what you should be using.
For that, you need to figure out the time that's at 45 seconds from the current minute. Some simple math gives that:
t = time.time()
minute = 60 * (t \\ 60) #Use integer division!
s.enterabs(minute + 45, ...)
s.run()
The stuff inside the ... specifies what you want to run/schedule, just read up on the package doc to figure out the format.
Then just put that scheduling into your loop and it should all be good, and no need for the sleep(60) no more.

How to implement a timing function in 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

Time actions in Python

I want to run a part of my loop for a certain time: 60 seconds. Afterwards I set a boolean flag and continue at another point. Does Python have something like a stopwatch? Maybe this is OS specific: it's targeted against a Linux env.
Sleeping a couple of seconds is easy... no question. ;) I want the opposite.
You could use the time.time() method:
import time
endtime = time.time() + 60
while time.time() < endtime:
# do something
Note - you probably don't want to use time.clock() as this measures CPU time rather than wall time.
You could use time.time() to set the begin of the loop, and later check if the passed time is greater than 60 seconds. But then you'll have a problem if the clock changes during the loop (very rare case) - so you should check for negative differences, too.
import time
begin = time.time()
for something:
# do something
if not (begin <= time.time() <= begin + 60):
break
As far as I know, Python does not include a stop watch class like in C#, for example.

Categories