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
Related
How can i stop a while loop after a certain time in which the sleep function is used. The condition inside a while loop does not work correctly because the sleep function pauses the execution of the code.
In this case i have delay for 40 seconds before a while loop stops:
# timeout for 10 minutes
timeout = time.time() + 60*10
while True:
if time.time() >= timeout:
break
# do something
sleep(20)
# do something
sleep(20)
you may use the code below.
import datetime
import time
timeout = datetime.datetime.now() + datetime.timedelta(seconds=20) # define here!
while True:
now = datetime.datetime.now()
if now >= timeout:
print('time is up !')
break
else:
print('do something')
time.sleep(5) # define here!
continue
Looks like you need a variable sleep duration.
Something like this:
from time import time, sleep
timeout = time() + 10 * 60
while time() < timeout:
# do some work
sleep_duration = min(20, timeout - time())
sleep(sleep_duration)
This means that the sleep will be at most 20s
Probably, the fastest solution will be to set the certain amount of sleep.
timeout = time.time() + 60*10
while time.time() < timeout:
# do something
# added clipping negative numbers too
time_left = max(0,min(20, timeout - time.time()))
sleep(time_left)
if time_left == 0:
break
time_left = max(0,min(20, timeout - time.time()))
# do something
sleep(time_left)
Not the most elegant solution. But should work
I need my code to stop and wait until the next day. The time does not matter, I just need it to continue when the date changes.
currentDate = datetime.datetime.now()
future = datetime.datetime(currentDate.year, currentDate.month,
(currentDate.day + 1))
time.sleep((future-currentDate).total_seconds())
The code pauses but does not continue after
Two options here with comments.
First do imports
import datetime
import time
one uses a while loop - probably not a good solution but highlights one way to wait for a condition to be met.
def loop_until_tomorrow():
""" Will use a while loop to iterate until tomorrow """
#get current date
currentDate = datetime.datetime.now().date()
# loop attempts
times = 0
# this will loop infiniatly if condition is never met
while True:
# increment by one each iteration
times += 1
#get date now
now = datetime.datetime.now().date()
if currentDate != now:
# return when condition met
print("\nDay has changed")
return
else:
# print attempts and sleep here to avoid program hanging
print(f"Attempt: {times}".ljust(13) + " - Not tomorrow yet!", end="\r")
time.sleep(5)
the other - sleeps for the amount of seconds from now till tomorrow
def sleep_until_tomorrow():
"""wait till tomorrow using time.sleep"""
#get date now
now = datetime.datetime.now()
#get tomorrows date
tomorrow_date = now.date() + datetime.timedelta(days=1)
#set to datetime
tomorrow_datetime = datetime.datetime(year=tomorrow_date.year, month=tomorrow_date.month, day=tomorrow_date.day, hour=0, minute=0, second=0)
#get seconds
seconds_til_tomorrow = (tomorrow_datetime-now).total_seconds()
#sleep
time.sleep(seconds_til_tomorrow)
You can use schedule for that purpose, which will give you the flexibility to refactore the code when needed without having to write a chunck of code.
from schedule import every, repeat, run_pending
import time
#just to give you the idea on how to implement the module.
#repeat(every().day.at("7:15"))
def remind_me_its_a_new_day():
print("Hey there it's a new day! ")
while True:
run_pending()
time.sleep(1)
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.
I want to run a function every 5 minutes, it must be at a "round" intervals, for example :
12:05:00, 12:10:00, 12:15:00...
It cannot be like this:
12:06:00, 12:11:00, 12:16:00...
Or like this:
12:05:14, 12:10:14, 12:15:14...
What is the most accurate way to do this in python?
You could use a threading.Timer. You have to do some math to calculate the next run time. datetime has a handy replace method for that.
from datetime import datetime, timedelta
from threading import Timer
from time import sleep
import random
def schedule_next_run():
sleep_time = get_sleep_time()
t = Timer(sleep_time, do_work)
t.daemon = True
t.start()
print(f'sleeping for {sleep_time} seconds')
def get_sleep_time():
now = datetime.now()
last_run_time = now.replace(minute=now.minute // 5 * 5, second=0, microsecond=0)
next_run_time = last_run_time + timedelta(minutes=5)
return (next_run_time - now).total_seconds()
def do_work():
now = datetime.now()
print('Doing some work at', now)
sleep(random.uniform(0, 29))
print('Work complete. Scheduling next run.')
schedule_next_run()
print('Starting work schedule')
schedule_next_run()
input('Doing work every 5 minutes. Press enter to exit:\n')
On my system, the function fires within a half millisecond of the target time
Note that the time calculation rounds down and then adds a timedelta to carefully wrap around the end of each hour. You would want to ponder how this will behave around daylight savings changes.
Suggestion: move all this logic to a class to clean it up.
You can use datetime and condition.
import datetime
while True:
current_time = datetime.datetime.now()
if current_time.second % 5 == 0 and current_time.minute % 1 == 0 and current_time.microsecond == 0:
print(current_time)
hope this helps.
import datetime, time
def some_function():
ran_once = True
while True:
current_time = datetime.datetime.now()
if current_time.minute % 5 == 0 and current_time.second % 60 == 0 and not ran_once:
print(current_time) # DO YOUR WORK HERE
ran_once = True
elif current_time.minute % 5 == 0 or current_time.second % 60 != 0:
if current_time.second % 60 == 0:
print("Time to wait:", 5 - (current_time.minute % 5), "minutes and 0 seconds")
else:
print("Time to wait:", 4 - (current_time.minute % 5), "minutes and ", end="")
print(60 - (current_time.second % 60), "seconds")
time.sleep( (4 -(current_time.minute % 5))*60 + 60 -(current_time.second % 60))
ran_once = False
The above code runs at intervals of 5 minutes. Initially, the main thread sleeps for the number of seconds required to reach the perfect timestamp. For example, if the program is started at 7:28:30 then it is going to sleep for 90 seconds and then start at 7:30:00. From then on it will wait for 5 minutes before it runs the required functionality again.
Also, I think the performance of firing up at the exact second really varies on how your system handles the threads.
I am trying to run the below code. It fails to run for 5 minutes, can you please let me know what the issue is here. I am trying to run this in background by saving as .pyw and alert me after finishing 1 hours, as per what is passed in timer arguments.
import time
import ctypes
def timer(minutes):
seconds = minutes * 60
start = time.time()
time.clock()
elapsed = 0
while elapsed < seconds:
elapsed = time.time() - start
time.sleep(1)
timer(5) #would want enter in hours not in seconds
ctypes.windll.user32.MessageBoxA(0,"DoneToday", "Dones", 0)
Your timer() function is infinitely looping.
After your while elapsed < seconds: loop, two lines down, you've put timer(5). So that just calls itself again, and again, again...
Once you remove this line, it will work as expected:
timer(5) #would want enter in hours not in seconds
And as #vermillon mentioned, any reason you're not just doing time.sleep(minutes * 60)? I'm assuming you plan to do something else in that loop, other than just counting time.
Edit: For the OP to see running code
>>> def timer(minutes):
... seconds = minutes * 60
... start = time.time()
... time.clock()
... elapsed = 0
... while elapsed < seconds:
... elapsed = time.time() - start
... time.sleep(1)
... ctypes.windll.user32.MessageBoxA(0,"DoneToday", "Dones", 0)
... print 'also printing Done so you can see it'
...
>>> timer(0.1)
also printing Done so you can see it
>>>
If you want a timer that shows minutes and seconds remaining, then here's the snippet for you:
import time
import sys
def run_timer(seconds):
for remaining in range(seconds, 0, -1):
sys.stdout.write("\r")
minutes = 0
seconds = remaining
if remaining > 60:
minutes = int(seconds/60)
seconds = int(seconds%60)
else:
seconds = remaining
sys.stdout.write("{:2d} minutes {:2d} seconds remaining.".format(minutes,seconds))
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write("Timer complete")
run_timer(120)