I'd like to schedule a repeated timed event in python like this:
"at time X launch function Y (in a separate thread) and repeat every hour"
"X" is fixed timestamp
The code should be cross-platform, so i'd like to avoid using an external program like "cron" to do this.
code extract:
import threading
threading.Timer(10*60, mail.check_mail).start()
#... SET UP TIMED EVENTS HERE
while(1):
print("please enter command")
try:
command = raw_input()
except:
continue
handle_command(command)
Create a dateutil.rrule, rr for your schedule and then use a loop like this in your thread:
for ts in rr:
now = datetime.now()
if ts < now:
time.sleep((now - ts).total_seconds())
# do stuff
Or a better solution that will account for clock changes:
ts = next(rr)
while True:
now = datetime.now()
if ts < now:
time.sleep((now - ts).total_seconds() / 2)
continue
# do stuff
ts = next(rr)
Related
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)
Using pytz to get a time. When the time is equal to a variable (string time), I want text to be printed (eventually a sound to be played). The time is iterating, but I can not get the statement to print when there is a match.
#imports
import time
from datetime import datetime
import pytz
#current time
def clocktime():
while True:
tz_syd = pytz.timezone("Australia/Sydney")
Sydney_Time = datetime.now(tz_syd).strftime("%H:%M:%S")
time.sleep(1)
#iterator to check for time match
def alarmsystem(clocktime):
TestCaseA = "20:52:16"
TestCaseB = "20:53:29"
while True:
if clocktime == TestCaseB:
print("Time B Triggered")
elif clocktime == TestCaseA:
print("Time A Triggered")
print(alarmsystem(clocktime()))
Any help greatly appreciated!
Your function clocktime() never stops running. Nor does it return or share anything about the time with alarmsystem().
When you write alarmsystem(clocktime()), the code will run and do clocktime() first. When ever clocktime() is done (never) it will send the return value (None in you case) to the function alarmsystem().
I assume what you want is that clocktime() runs continuously in the background, and the function alarmsystem() will trigger when that timer hits a certain time.
For this you need to have clocktime() run in a different thread.
If all your program needs to do is trigger on a certain time you can use the following code:
def alarmsystem():
TestCaseA = "20:52:16"
TestCaseB = "20:53:29"
while True:
tz_syd = pytz.timezone("Australia/Sydney")
clocktime = datetime.now(tz_syd).strftime("%H:%M:%S")
if clocktime == TestCaseB:
print("Time B Triggered")
elif clocktime == TestCaseA:
print("Time A Triggered")
I am trying to Execute the function in tkinter as I want function to run in background I have done following code. Also I am trying to execute it inside a while loop but its not looping through.
t1 = dt.time(hour = 13, minute= 24)
t2 = dt.time(hour= 13, minute= 4)
timetable = [t1, t2]
root = Tk()
def Alarm():
current_time = now_time.strftime("%H:%M:%S")
print(current_time)
print(timetable[0])
while True:
if timetable[0] <= dt.datetime.now().time():
print("Its time")
break
Alarm()
root.mainloop()
print statements are only for testing. The logic I am using in alarm clock is also not executing properly as it tells ""Its time" even after time has passed. I have tried following methods before.
method 1:
for i in reversed(timetable):
i_time = i
#print (i_time)
#print(now_time.strftime("%H:%M"))
while True:
if dt.datetime.now().time() < i_time:
#if i_time <= dt.datetime.now().time():
print("Its Time")
break
method 2:
for i in timetable:
current_time = dt.datetime.now().time()
alarm_time = i
while True:
if current_time < alarm_time:
if current_time <= alarm_time:
print("its time", alarm_time)
Using for loop was my first goal but for loop isn't executing properly. It only gets 1st element and doesn't go to 2nd element even if first element has passed so I have decided to go with if,elif,else statement
You can use the after method to run a function after a certain amount of time has elapsed. You should use it rather than creating a loop.
You simply need to convert the alarm time to a number of milliseconds, then use that to ring the alarm at the given time. For example, to ring an alarm in one hour you would do this:
def ring_alarm():
print("Its time")
delay = 60 * 60 * 1000 # 60 min/hour, 60 secs/min, 1000ms/sec
root.after(delay, ring_alarm)
I am going with if..else response for executing alarm as
current_time = dt.datetime.now().time()
if timetable[0] == current_time:
print("Its time")
break
I was breaking While loop in wrong place as well an typo from my end.
I'm trying to write a program to remind a user to take breaks. Here is the code:
import datetime
import os
from playsound import playsound
import time
# current_time = datetime.datetime.now()
# print(current_time)
running = True
while running:
current_time = datetime.datetime.now()
new_time = datetime.datetime.now()
# print(current_time)
breaktime = datetime.timedelta(
days=0,
hours=0,
minutes=1
)
times = datetime.timedelta(seconds=5)
time.sleep(6)
new = current_time + times
if new_time == new:
print("hello")
playsound('Take_Flight.mp3')
running = False
break
The program does not play the sound Take_Flight.mp3 and it does not print hello.
How can I make it work?
I think the reason your alarm does not ring is because of the break statement at the bottom line of your code. The while loop simply ends without looping over and over again as you intended. I believe if you remove that your code will work. As an alternative to what you wrote you can also make the program wait for 5 min and then ring without getting the current time:
while True
time.sleep(300000)
print("hello")
playsound('Take_Flight.mp3')
I'm trying to write a Python program that reproduces a sound every certain hour, but it doesn't really work. When I test the code and the specified time comes, it will keep repeating the sound forever.
Here is the code:
import os
from datetime import datetime
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
#I also tested with if but it didn't work
while currentHour==15 and currentMin==33:
os.system("aplay /home/pi/sound.wav") #Plays the sound thru aplay
Your logic is wrong.
First of all, the while loop will most likely end in the first iteration and you want the program to continue till you tell it to.
In addition to that, you don't update the now variable inside the loop, which is basically a bad idea.
For example, this code will continue running and when it is 15:33, a sound will be played only once.
myHour = 15
myMin = 33
is_played = False
while True:
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
if currentHour == myHour and currentMin == myMin and not is_played:
is_played = True
os.system("aplay /home/pi/sound.wav")
if currentHour != myHour or currentMin != myMin:
is_played = False
Xiaotian Pei suggested a great idea, to efficiently use your CPU resource, lets use the Timer module:
def to_play_sound(hour, min):
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
if currentHour == hour and currentMin == min and not is_played:
is_played = True
os.system("aplay /home/pi/sound.wav")
if currentHour != myHour or currentMin != myMin:
is_played = False
while True:
t = Timer(30.0, to_play_sound, [15, 33])
t.start()
J.F. Sebastian has also suggested a great idea:
import datetime
import subprocess
while True:
now = datetime.now()
# compute `deadline`
while True:
deadline = now.replace(hour=hour, minute=min)
if deadline > now:
break
else:
deadline += datetime.timedelta(1)
sleep_until(deadline) # sleep
subprocess.check_call(['aplay', '/home/pi/sound.wav']) # play the sound!
Read how sleep_until was implemented here.
It's a complement to #bshuster13 's answer.
What you need is actually a timer. Using a busy loop and detect if it's the right time to do something is not a good idea. Take a look at Timer in python. I think you will come up with a better solution.