I'm sure I am missing something very basic... I have a python script that calls a sleep function. I'd like the main thread (in this case) to sleep for 1 hour (3600 seconds).
Here is the relevant code reproduced:
import time
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
print("Sleep", flush=True)
time.sleep(3600)
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
print("Done sleeping", flush=True)
The output after 2 hours is:
Current Time = 08:45:45
Sleep
But my code never exits the sleep function to print the finish time or "Done sleeping" message.
(I added the flush parameter to the print statement to eliminate potential buffering, but I don't think that's relevant here).
Any thoughts on why my code doesn't exit the sleep function after 1 hour?
Thanks.
You could try a loop like this to tell you how long it takes to time out.
import time
from time import perf_counter
from datetime import datetime
start = perf_counter()
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
print("Sleep", flush=True)
# time.sleep(3600)
for i in range(3600):
print("Seconds sleeping:{}".format(i))
time_elapsed = perf_counter() - start
print("Elapsed Time =", time_elapsed)
time.sleep(1)
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
print("Done sleeping", flush=True)
I added the perf_counter that #Jortega suggested.
I ran it for 1 hour (3600) seconds, and in this case it finished, but also showed the sleep function "drifted" by about 18 seconds over the 1 hour period. Output below:
Seconds sleeping:3597
Elapsed Time = 3615.837408959
Seconds sleeping:3598
Elapsed Time = 3616.842702875
Seconds sleeping:3599
Elapsed Time = 3617.847937667
Current Time = 15:20:32
Done sleeping
This is interesting but unfortunately, I'm still not sure why the following code does not work:
import time
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
print("Sleep", flush=True)
time.sleep(3600)
now = datetime.now() <================== Code never executes.
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
print("Done sleeping", flush=True)
If anyone has any suggestions, it would be appreciated.
Related
Background
I am querying data every 'x' number of minutes & performing various calculations.
I came up with two ways of doing it.
I like the first one better. The reason is if I add more in-between code that takes 'y' time to compute, it would still run every 'x' minutes. Using time.sleep, I would need to calculate 'y' time remaining in order to make sure 'x' update was always consistent.
While Loop One:
import datetime
from datetime import datetime, timedelta
import time
frequency = 10/60
first_start = True
target_time = datetime.now()
while(True):
if(target_time < datetime.now()):
if(first_start):
start_time = datetime.now()
first_start = False
else:
start_time = end_time
end_time = start_time + timedelta(minutes=frequency)
target_time = end_time + timedelta(minutes=frequency)
print("Start: ", start_time)
print("End: ", end_time)
print("Target: ", target_time)
Or I can swap the while loop out with the following:
While Loop Two:
first_start = True
target_time = datetime.now()
while(True):
if(first_start):
start_time = datetime.now()
first_start = False
else:
start_time = end_time
end_time = start_time + timedelta(minutes=frequency)
target_time = end_time + timedelta(minutes=frequency)
print("Start: ", start_time)
print("End: ", end_time)
print("Target: ", target_time)
time.sleep(frequency*60)
Isn't time.sleep() doing something very similar just in the background (while loop checking that 'x' number of seconds has been completed before returning)?
Or is it doing something more efficient?
Both operations are blocking. You can accheive the same by using crontab or celery beat or apscheduler without blocking your CPU
there was a lot of models available here of a countdown timer but almost all of them does not have a millisecond value
the model im using :
import time
def countdown(t):
while t:
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
print(timer, end="\r")
time.sleep(1)
t -= 1
print('Fire in the hole!!')
# input time in seconds
t = input("Enter the time in seconds: ")
# function call
countdown(int(t))
i understand the divmod() method but i still find it difficult to understand how to extract milliseconds from this
Your code does not keep track of any milliseconds. You sleep(1) - which should sleep at least 1000ms (maybe more - see here - it depends on what is going on on your PC elsewise).
To display any ms you need to capture the current time somehow:
from datetime import datetime, timedelta
import time
def countdown(seconds):
started = datetime.now()
ended = started + timedelta(seconds=seconds)
while datetime.now() < ended:
print(f"Waiting for {ended-datetime.now()}", flush=True)
time.sleep(1)
now = datetime.now()
if now > ended:
print(f'Sorry, I overslept: {now-ended}')
print('Fire in the hole!!')
# input time in seconds
t ="4"
# function call
countdown(int(t))
To get:
Waiting for 0:00:04
Waiting for 0:00:02.995686
Waiting for 0:00:01.995361
Waiting for 0:00:00.980077
Sorry, I overslept: 0:00:00.020248
Fire in the hole!!
You can format the timedelta to your conveniece - more solutions to that f.e. here: Formatting timedelta objects.
Sleeping for a calculated time like
while datetime.now() < ended:
remainder = ended-datetime.now()
print(f"Waiting for {remainder}", flush=True)
time.sleep(min(1, ( ended-datetime.now()).total_seconds()))
could try to minimize your over-sleep time on the last loop. You could also try to do this for every loop by calculating what you need to sleep if need better 1s precision.
But in the end your loops may still be off due to factors you can not influence.
fulldate = datetime.datetime.strptime(date + ' ' + time, "%Y-%m-%d %H:%M:%S.%f")
fulldate = fulldate + datetime.timedelta(milliseconds=500)
This should solve your problem,
https://docs.python.org/2/library/datetime.html#timedelta-objects
i'd like to know how to sync datetime with system time in real time. what i mean is the code always prints the same hour same minute and same seconds if i loop the code. this is my code
from datetime import datetime
import os
from time import sleep
def clear():
os.system('cls')
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
while True:
time = print("Current Time =", current_time)
sleep(1)
clear()
i need help for this thx!
You are currently creating the date-time object only once with the line. This means the time is only looked up once and then that value is stored in the variable.
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
All you need to do is move those two lines into your loop. That way, the time is looked up on each loop iteration and you get new values. The modified code:
from datetime import datetime
import os
from time import sleep
def clear():
os.system('cls')
while True:
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
time = print("Current Time =", current_time)
sleep(1)
clear()
Thanks for the answer! i also modify the code a little bit to make it a little bit better
from datetime import datetime
from time import sleep
while True:
now=datetime.now()
current_time=now.strftime("%H:%M:%S")
time=print("Current Time : ", current_time, end=\r)
sleep(1)
I want to make a programme who print "hey" every 5 seconds
mine is printing every 5 seconds but more than one time.
import datetime
now = datetime.datetime.today()
objectif = datetime.timedelta(seconds = 50)
later = objectif+now
inc = 0
while later > datetime.datetime.today():
if datetime.datetime.today().second%5==0 and later.microsecond == datetime.datetime.today().microsecond:
print "hey"
How can I print "hey" only one time per 5 seconds?
You can use time.sleep()
The following will print 'hey' ever 5 seconds to a limit of 50 seconds
import datetime
from time import sleep
end_time = datetime.datetime.now() + datetime.timedelta(seconds = 50)
while end_time > datetime.datetime.now():
print("hey")
sleep(5)
I am creating a job which should run after every 10 seconds for next 2 hours, how can I do that?
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
#sched.scheduled_job('interval', seconds=10)
def timed_job():
print('This job is run every 10 seconds.')
sched.start()
How can I stop this scheduled job to stop after 2 hours?
You could use the time built-in module. You can do start_time = time.time() to get the start time. Then do a boolean test before running your code of if time.time()-start_time < 7200 and then your code. Otherwise it would cancel. Then your code will continue to run until 7200 seconds(2 hours) has passed.
import time
def hello():
print("hello-world ")
start_time = time.time()
while(time.time() - start_time < 20):
hello()
time.sleep(5)