Bright minds of Stackoverflow, I have a quest for you.
Currently I am running a loop in which calculations and data aquisition happen. These get more and more complicated over time. I want each run of the loop to last exactly one second. Due to the growing time of the calculations a simple "sleep(1)" at the end does not really help.
while True:
#here calculations happen that take more and more time
print 'some of the data'
sleep(1)
I was hoping to use datetime to calculate the seconds/milliseconds before these calculations and after to enter the difference into the sleep command. But i can't quite get my head around it. Can anyone help me out?
a=datetime.now()
#calculations
b=datetime.now()
calctime=(b-a).total_seconds()
sleep(1-calctime)
Try this:
from datetime import datetime
import time
def test():
a = datetime.now()
# calculations
b = datetime.now()
calctime = (b - a).total_seconds()
print("one")
time.sleep((1 - calctime) if (1-calctime)>0.0 else 0) #if your calculation already took 1 or more than 1 second then then make the waiting time 0
print("two")
test()
a=datetime.now()
#calculations
b=datetime.now()
calctime=b-a
ms = calctime.microseconds
if calctime.seconds == 0:
sleep(1-ms/1000000)
Additional info here: Python speed testing - Time Difference - milliseconds
Related
I am very very new to python and I am trying to make a simple timer app with it.
So if I input a number, like 30, the code should start counting down and output
>>> 30
>>> 29
>>> 28
>>> 27
and so on..
I am trying to get some logic into my brain. I was trying to do this since to days with same code in different places.
import time
x = input("seconds to blast off: ")
for z in range(x):
timer.sleep(x)
print("blast off")
This is all I have written and I am stuck here.
There's a few things here that need a little work.
First, input will always returns a string, so x is also a string. So if the user were to input '30', you would run for z in range('30'): which will error. Instead, you should cast x to an int with int(x).
Next, it's time.sleep, not timer.sleep
The way I'd implement the counter part personally would be to keep track of the start time, then calculate the end time. Then, find the difference between the time in the iteration and the end time and loop while that is greater than 0. It might look like this:
import time
x = int(input('Number of seconds: '))
end = time.time() + x
while end - time.time() > 0:
print(round(end - time.time()))
time.sleep(1)
Try this:
import time
sec = int(input('No. of seconds: '))
print(sec)
for s in range(sec):
sec = int(sec) - 1
time.sleep(1)
if sec == 0:
print("Blast Off")
else:
print(str(sec))
You got quite close to the solution.
timer.sleep() takes in the number of seconds.
Although, you could have found such answers on the web.
I was testing a program to do something every N seconds, but I bumped into a weird problem.
If I use something simple like this:
import time
def main():
start_t = time.time()
while(True):
if (time.time()-start_t)%10 == 0:
print("Test")
if __name__ == "__main__":
main()
the program works as expected, i.e. it prints "Test" every 10 seconds.
However, I made a small modification, because I need to check at every iteration the current date...if I change the program to this:
import time
from datetime import datetime
def main():
start_t = time.time()
path_screenshots = "screenshots"
while(True):
path_screenshots_today = f"{path_screenshots}/{datetime.now().strftime('%Y_%m_%d')}/"
if (time.time()-start_t)%10 == 0:
print(f"Checking folder {path_screenshots_today}...")
if __name__ == "__main__":
main()
I would expect the program to print "Checking folder {path_screenshots_today}" every 10 seconds again, but instead it keeps running, without printing anything.
I understand that the result of the operation (time.time()-start_t)%10 is never precisely equal to 0, which might be creating the issue...but then, why does it even work in the first case?
I suspect it is working in the first case because the loop is running fast enough that it happens to line up. The lag created by creating path_screenshots_today (particularly the datetime.now() call) causes it not to line up as often. To actually do what you want, try:
import time
from datetime import datetime
def main():
last = time.time()
path_screenshots = "screenshots"
while True:
path_screenshots_today = f"{path_screenshots}/{datetime.now().strftime('%Y_%m_%d')}/"
if time.time() - last >= 10:
last = time.time()
print(f"Checking folder {path_screenshots_today}...")
if __name__ == "__main__":
main()
The first case works because the time is checked frequently enough, which does not happen in the second case because of the delay introduced by the string formatting. A more robust way is the following:
start_t = time.time()
while True:
path_screenshots_today = f"{path_screenshots}/{datetime.now().strftime('%Y_%m_%d')}/"
tt = time.time()
if tt - start_t >= 10:
print(f"Checking folder {path_screenshots_today}...")
start_t = tt # set last check time to "now"
And an even better way would be:
while True:
path_screenshots_today = f"{path_screenshots}/{datetime.now().strftime('%Y_%m_%d')}/"
print(f"Checking folder {path_screenshots_today}...")
time.sleep(10)
This avoids "busy waiting", i.e. keeping the CPU running like crazy.
It's a coincidence of how often the check is happening. If you actually loop over and print your value, you'll notice it's floating point:
while(True):
print('Current value is, ', (time.time()-start_t)%10)
You'll see output like this:
Current value is, 0.45271849632263184
Current value is, 0.45272231101989746
Given that you're doing so little in your loop, the odds are good that you'll coincidentally do that evaluation when the current value is exactly 0.0. But when you add some extra computation, even just the string formatting in datetime, each iteration of your loop will take a little longer and you might just happily skip over 0.0.
So strictly speaking, you should cast your value to an int before comparing it to 0. Eg, int((time.time() - start_t) % 10) == 0. That will be true for an entire second, until the modulus value is once again not zero, a second after it's first true.
A better solution, however, is to probably just use the time.sleep() function. You can call time.sleep to sleep for a number of seconds:
time.sleep(10) # Sleep for 10 seconds
I need to call a function, exactly 08:00, 18:00, 22:00 hours. I've created a example to test the comparison between hours. When the current time reaches one of those horary. Put in inside a While loop thinking this example would work as a stopwatch, but I think I'm wrong. How is the best way to compare those values?
currentH= dt.datetime.now().strftime("%H:%M:%S")
h = "16:15:10"
while True:
if(currentH==h):
print 'Ok'
print 'The current Hour is: '+h
import datetime as dt
import time
currentH= dt.datetime.now().replace(microsecond=0).time()
hrs = ['00:02', '12:00']
for i in range(len(hrs)):
h = [int(x) for x in hrs[i].split(':')]
h = dt.datetime.now().replace(hour=h[0], minute=h[1], second=0,microsecond=0).time()
hrs[i] = h
while True:
currentH = dt.datetime.now().replace(microsecond=0).time()
print(currentH)
if currentH in hrs:
print('Time is now',currentH)
time.sleep(1)
The biggest problem with your code is that you never call now() again inside the loop, so you're just spinning forever comparing the initial time to 16:15:10.
While we're at it: Why convert the time to a string for comparison instead of just comparing times?
But there are bigger problems with this design that can't be fixed as easily.
What happens if you check the time at 16:15, then go to sleep, then wake up at 16:25? Then now() never returns 16:15:10.
Also, do you really want to burn 100% CPU for 10 hours?
A better solution is to write a sleep_until function:
def sleep_until(target):
left = target - dt.datetime.now()
if left > dt.timedelta(seconds=0):
time.sleep(left.total_seconds())
(If you're using Python 2.7 or 3.4, it's a bit more complicated, because sleep will wake up early if there's a signal. But to handle that case, you just need to add a while True: loop around the whole thing.)
Now, the only tricky bit is working out the first time you need to sleep until, which isn't all that tricky:
waits = itertools.cycle(dt.timedelta(hours=wait) for wait in (10, 4, 10))
now = dt.datetime.now()
start = dt.datetime.combine(dt.date.today(), dt.time(hour=8))
for wait in waits:
start += wait
if start > now:
break
And now, we just loop over the waits forever, sleeping until each next time:
for wait in waits:
sleep_until(start)
print('Time to make the donuts')
start += wait
Or, of course, you could just grab one of the many scheduling libraries off PyPI.
Or just use your platform's cron/launchd/Scheduled Tasks API to run your script.
I have some problem here. I want to stop the print command at desired time. I figured out some codes and it still keep looping. Here the code,
import time
t = time.strftime("%H%M%S")
while ti:
print(time.strftime("%H%M%S"))
time.sleep(1)
if t = ("140000"): #just example of time to stop print
break
Thanks
t = time.strftime("%H%M%S")
is only executed once before the loop, so t's value doesn't ever change.
Your approach is the worst method of checking time difference; python's datetime framework allows for subtraction of timestamps and thus, you can check the time since something else happened easily without doing any string comparisons...
This will work
import time
t = time.strftime("%H%M%S")
while t:
t = time.strftime("%H%M%S")
print(time.strftime("%H%M%S"))
time.sleep(1)
if t == ("140000"): #just example of time to stop print
break
You had some bugs in your code
while ti: -- > while t:
if t = ("140000"): --> if t== ("140000"):
and you were missing this line t = time.strftime("%H%M%S")
time.sleep(1) may sleep less or more than a second therefore t == "140000" is not enough.
To stop a loop at a given local time:
import time
from datetime import datetime
stop_dt = datetime.combine(datetime.now(), datetime.strptime("1400", "%H%M").time())
stop_time = time.mktime(stop_dt.timetuple())
while time.time() < stop_time:
print(time.strftime("%H%M%S"))
time.sleep(max(1, (stop_time - time.time()) // 2))
time.time() returns "seconds since the epoch" -- unlike strings comparison it works across a midnight.
The sleep interval is a half of the remaining time or one second (whatever larger).
time.mktime() may return a wrong result if stop time is during an end-of-DST transition ("fall back") when the local time is ambiguous (the string-based solution may stop twice in this case).
Try this:
import time
while ti:
t = time.strftime("%H%M%S")
print(time.strftime("%H%M%S"))
time.sleep(1)
if t = ("140000"): #just example of time to stop print
break
I have to time the implementation I did of an algorithm in one of my classes, and I am using the time.time() function to do so. After implementing it, I have to run that algorithm on a number of data files which contains small and bigger data sets in order to formally analyse its complexity.
Unfortunately, on the small data sets, I get a runtime of 0 seconds even if I get a precision of 0.000000000000000001 with that function when looking at the runtimes of the bigger data sets and I cannot believe that it really takes less than that on the smaller data sets.
My question is: Is there a problem using this function (and if so, is there another function I can use that has a better precision)? Or am I doing something wrong?
Here is my code if ever you need it:
import sys, time
import random
from utility import parseSystemArguments, printResults
...
def main(ville):
start = time.time()
solution = dynamique(ville) # Algorithm implementation
end = time.time()
return (end - start, solution)
if __name__ == "__main__":
sys.argv.insert(1, "-a")
sys.argv.insert(2, "3")
(algoNumber, ville, printList) = parseSystemArguments()
(algoTime, solution) = main(ville)
printResults(algoTime, solution, printList)
The printResults function:
def printResults(time, solution, printList=True):
print ("Temps d'execution = " + str(time) + "s")
if printList:
print (solution)
The solution to my problem was to use the timeit module instead of the time module.
import timeit
...
def main(ville):
start = timeit.default_timer()
solution = dynamique(ville)
end = timeit.default_timer()
return (end - start, solution)
Don't confuse the resolution of the system time with the resolution of a floating point number. The time resolution on a computer is only as frequent as the system clock is updated. How often the system clock is updated varies from machine to machine, so to ensure that you will see a difference with time, you will need to make sure it executes for a millisecond or more. Try putting it into a loop like this:
start = time.time()
k = 100000
for i in range(k)
solution = dynamique(ville)
end = time.time()
return ((end - start)/k, solution)
In the final tally, you then need to divide by the number of loop iterations to know how long your code actually runs once through. You may need to increase k to get a good measure of the execution time, or you may need to decrease it if your computer is running in the loop for a very long time.