Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
from tkinter import *
from tkinter import messagebox
import pygame
import time
pygame.init()
def alarm_time():
hrs = int(hrs_opt_ctrl.get())
min = int(min_opt_ctrl.get())
tme = tme_ctrl.get()
if hrs == int(time.strftime('%I')) and min == int(time.strftime('%M')) and tme == time.strftime('%p'):
# Time is up. Play the sound
alarm_ringtone = pygame.mixer.music.load('alarm_noise.mp3')
pygame.mixer.music.play()
# Don't call after again
else:
# Not time, sleep for 1 second
window.after(1000, alarm_time)
def snooze_time():
snoz_min=(2,5,10,20,30,35,40,45,50,55,59)
snooze=True
while snooze:
try:
min = min + int(snoz_min[minute])
window.after((min)*1000,alarm_time)
except:
messagebox.showerror("Error 404", "Cannot Snooze for given Time")
if minute<=len(snoz_min):
minute+=1
elif minute!=len(snoz_min):
minute=0
else:
pass
snooze=False
window=Tk()
window.title('Alarm')
window.config(background='black')
logo=PhotoImage(file='alarm.gif')
lab_1=Label(window,text='Alarm',bg='black',fg='white',font=('Times',25,'bold')).grid(column=100,row=0)
lab_2=Label(window,bg='black',image=logo).grid(column=300,row=0)
lab_3=Label(window,text='Hours',bg='black',fg='white',font=('Comic',10,'bold')).grid(column=50,row=130)
lab_4=Label(window,text='Minutes',bg='black',fg='white',font=('Comic',10,'bold')).grid(column=85,row=130)
opt_hrs=[]
opt_min=[]
opt_tme=('AM','PM')
minute=0
for i in range(1,13):
opt_hrs.append(i)
for j in range(0,60):
opt_min.append(j)
hrs_opt_ctrl=StringVar()
min_opt_ctrl=StringVar()
tme_ctrl=StringVar()
tme_ctrl.set(opt_tme[0])
hrs_lab=OptionMenu(window,hrs_opt_ctrl,*opt_hrs).grid(column=60,row=130,columnspan=15)
min_lab=OptionMenu(window,min_opt_ctrl,*opt_min).grid(column=86,row=130,columnspan=15)
tme_lab=OptionMenu(window,tme_ctrl,*opt_tme).grid(column=150,row=130)
but_1=Button(window,text='Set Alarm',font=('Comic',10,'bold'),command=alarm_time).grid(column=100,row=240)
but_2=Button(window,text='Snooze',font=('Comic',10,'bold'),command=snooze_time).grid(column=100,row=250)
window.mainloop()
The following code doesnt show any error when run but doesnt play the alarm.
The alarm file is in .mp3 extension and in the same folder as the project.
i probably think that something's wrong in the time module code
or the 'Set Alarm' button is not taking any input.The position of columns and rows are not accurate
As mentioned in the comments, you have it setup to only play the alarm iff the user clicks the button at the time the alarm is set to. Instead, you should check the time every second, and play the alarm at the given time:
def alarm_time():
hrs = int(hrs_opt_ctrl.get())
min = int(min_opt_ctrl.get())
tme = tme_ctrl.get()
if hrs == int(time.strftime('%I')) and min == int(time.strftime('%M')) and tme == time.strftime('%p'):
# Time is up. Play the sound
alarm_ringtone = pygame.mixer.music.load('alarm_noise.mp3')
pygame.mixer.music.play()
# Don't call after again
else:
# Not time, sleep for 1 second
window.after(1000, alarm_time)
Note, I convert everything to int because time.strftime('%I') and time.strftime('%M') return 0-pre-padded strings and your option box does not have 0-pre-padded values, so "1" != "01", etc.
Updated answer with multiple alarms and snooze. I just threw this together so there is plenty of room for improvement:
from tkinter import *
import pygame
import time
pygame.mixer.init()
window = Tk()
window.geometry('300x200')
window.title('Alarm')
#logo = PhotoImage(file='alarm.gif')
lab_1 = Label(window, text='Alarm Clock', font=('Times',20,'bold')).grid(column=200, row=0)
#lab_2=Label(window,image=logo).grid(column=300,row=0,columnspan=3)
lab_3 = Label(window, text='Hours', font=('Comic',10,'bold')).grid(column=50,row=10, columnspan=3)
lab_4 = Label(window, text='Minutes', font=('Comic',10,'bold')).grid(column=90,row=10, columnspan=3)
# Alarm class
class Alarm:
alarm_id = 1
def __init__(self, hours, minutes, ampm, sound_file):
self.sound_file = sound_file
# Convert hours, minutes, ampm to a timestamp
# Save time as a timestamp
t = time.localtime()
t = time.strptime(f"{t.tm_year}-{t.tm_mon}-{t.tm_mday} {hours} {minutes} {ampm}", "%Y-%m-%d %I %M %p")
self.alarm_time = time.mktime(t)
# Number of seconds to snooze
self.snooze_time = None
self.completed = False # Set to True after alarm has gone off
self.id = Alarm.alarm_id
Alarm.alarm_id += 1
# Every time this is called, it checks the time to see if the alarm should go off
def check_time(self, cur_time):
# Use alarm time or snooze time?
on_time = self.snooze_time if self.snooze_time else self.alarm_time
# Since might not be called when seconds is 0, check if it is with one minute of alarm time
time_diff = cur_time - on_time
if not self.completed and time_diff >= 0 and time_diff < 60:
self.completed = True
alarm_ringtone = pygame.mixer.music.load(self.sound_file)
pygame.mixer.music.play()
# Reset after 30 minutes - add 24 hours (daily timer)
elif self.completed and time_diff > 1800 and time_diff < 1860:
self.completed = False
self.snooze_time = None
self.alarm_time += 24 * 60 * 60
def snooze(self, minutes):
if self.completed and pygame.mixer.music.get_busy():
self.snooze_time = time.time() + (minutes * 60)
self.completed = False
pygame.mixer.music.stop()
# Convert to string for printing
def __str__(self):
id_str = f"[{self.id}]: "
if self.completed:
return id_str + ("Alarm in progress" if pygame.mixer.music.get_busy() else "Alarm completed")
elif self.snooze_time:
time_left = int(self.snooze_time - time.time())
minutes = time_left // 60
seconds = time_left % 60
if minutes:
return id_str + f"Snoozing for {minutes} minutes and {seconds} seconds"
else:
return id_str + f"Snoozing for {seconds} seconds"
else:
return id_str + f"Alarm set for {time.ctime(self.alarm_time)}"
# This list holds all alarms
all_alarms = []
# Tell all alarms to check the time
def check_alarms():
now = time.time()
for alarm in all_alarms:
print(f"Checking: {alarm}");
alarm.check_time(now)
# Call again after 1 second
window.after(1000, check_alarms)
# Creates a single object of the Alarm class
# Uses values from the option controls
def create_alarm():
hours = int(hrs_opt_ctrl.get())
minutes = int(min_opt_ctrl.get())
ampm = tme_ctrl.get()
alarm = Alarm(hours, minutes, ampm, "alarm.mp3")
all_alarms.append(alarm)
print(f"Adding: {alarm}");
# Snoozes all active alarms for 2 minutes
def snooze_current():
for alarm in all_alarms:
alarm.snooze(2)
but = Button(window, text='Set Alarm', font=('Comic',10,'bold'), command=create_alarm).grid(column=100,row=15)
snooze = Button(window, text='Snooze', font=('Comic',10,'bold'), command=snooze_current).grid(column=100,row=16)
opt_hrs = []
opt_min = []
opt_tme = ('AM','PM')
for i in range(1,13):
opt_hrs.append(i)
for j in range(0,60):
opt_min.append(j)
hrs_opt_ctrl = StringVar()
min_opt_ctrl = StringVar()
tme_ctrl = StringVar()
hrs_lab = OptionMenu(window, hrs_opt_ctrl, *opt_hrs).grid(column=70,row=10,columnspan=3)
min_lab = OptionMenu(window, min_opt_ctrl, *opt_min).grid(column=100,row=10,columnspan=3)
tme_lab = OptionMenu(window, tme_ctrl, *opt_tme).grid(column=120,row=10,columnspan=3)
# Fill with default values of current time
hrs_opt_ctrl.set(str(int(time.strftime('%I'))))
min_opt_ctrl.set(str(int(time.strftime('%M'))))
tme_ctrl.set(time.strftime('%p'))
check_alarms()
window.mainloop()
pygame.mixer.music.stop()
Related
I am making a stop watch in python which prints out the seconds passed and as soon as the user presses enter, it stops.
I am using multiprocessing to ask for an input and keep printing until an input is received. but the code is giving an EOF error for the input statement when I run it, what am I doing wrong?
import os
import multiprocessing
end = multiprocessing.Value('i',0)
def get_input(end):
x = input('')
end.value = 1
def print_time(end):
secs = 0
mins = 0
hrs = 0
x = input('start: ')
while True:
mins, secs = divmod(secs, 60)
hrs = 0
if mins > 60:
hrs, mins = divmod(mins, 60)
timer_display = '{:02d}:{:02d}:{:02d}'.format(hrs, mins, secs)
print(timer_display)
if end.value == 1:
break
time.sleep(1)
secs += 1
if __name__ == "__main__":
func1 = multiprocessing.Process(target = get_input, args = (end,))
func2 = multiprocessing.Process(target = print_time, args = (end,))
func1.start()
func2.start()
func1.join()
func2.join()
It's probably better to start/stop the stopwatch in the main program and just use one Process to display the timer. Something like this:
from multiprocessing import Process, Value
import time
def showTime(end):
start = time.time()
while end.value == 0:
elapsed = int(time.time() - start)
ss = elapsed % 60
mm = elapsed // 60 % 60
hh = elapsed // 3600
print(f'{hh:02d}:{mm:02d}:{ss:02d}')
time.sleep(1)
def main():
input('Press enter to start: ')
end = Value('i', 0)
Process(target=showTime, args=(end,)).start()
input('Press enter to stop: ')
end.value = 1
if __name__ == '__main__':
main()
Also, this technique allows for any potential drift due to processing time
I am aware of the .after method, but it requires a function to use.
I tried making a function that does nothing, but it just freezes the screen.
Is there a way to make it so it doens't modify the gui when doing .after? (I tried with a function that did, and it worked)
def doNothing():
return "nothing"
def init_timer(time=25):
global minutes
global onBreak
minutes = 0
onBreak = False
while True:
pomodoro()
def pomodoro():
global pomodoros
if pomodoros < 4:
setTimer(25)
while not(isTimerDone):
print("Timer In Progress")
setTimer(5)
while not(isTimerDone):
pomodoros += 1
else:
setTimer(30)
def timerDone():
global onBreak
global isTimerDone
isTimerDone = True
reminderTitle.config(text="The timer is done!")
onBreak = not(onBreak)
if onBreak:
reminderTitle.config(text="Go on break!")
else:
reminderTitle.config(text="Get to work!")
timer.config(text="Completed")
playsound(f'{os.getcwd()}/Audio/notification.mp3')
def setTimer(mins=25):
global isTimerDone
isTimerDone = False
timer.config(text="In Progress")
window.after(mins * 60 * 1000, timerDone)
This problem occurs when you use while function . So, in order to make your program work properly you have to use .after only , not inside a while function .Here is an example that you could base on to improve your program :
import tkinter as tk
root = tk.Tk()
clock = tk.Label(root)
k = 0
def timing(time):
'''time in minutes'''
global k
k = time
clock.configure(text = 'you still have : ' + str(time) + ' minutes')
def change_value():
global k
if k > 0:
k = k-1
clock.configure(text = 'you still have : ' + str(k)+' minutes')
root.after(60000,change_value)
else :
clock.configure(text = "it's over")
root.after(60000,change_value)
timing(5)
clock.pack()
root.mainloop()
My code:
def timer():
while True:
try:
when_to_stop = 90
except KeyboardInterrupt:
break
except:
print("error, please star game again")
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" +
str(s).zfill(2) # got cut off, belongs to the line before this
print("time:", time_left + "\r", end="")
if time_left == 0:
print("TIME IS UP!")
time.sleep(1)
when_to_stop -= 1
This works perfectly fine, except that time.sleep means my whole program sleeps, so anything after that while stop for 90 seconds. Any way to fix that?(or make a new timer without time.sleep?)
I think that, alternatively, you could keep track of when the timer starts, and check the time by seeing if the time that's passed is longer than the timer is supposed to last. I'm not sure how much you know about classes and objects in Python, but here is the solution that came to mind:
import datetime
class Timer:
def __init__(self,**kwargs):
self.start = datetime.datetime.now()
self.length = datetime.timedelta(**kwargs)
self.end = self.start+self.length
def isDone(self):
return (self.end-datetime.datetime.now()).total_seconds()<=0
def timeLeft(self):
return self.end-datetime.datetime.now()
def timeElapsed(self):
return datetime.datetime.now()-self.start
Even if you don't quite understand the class itself, if you put it in your code it should work like a charm:
#This has the same options as:
#class datetime.timedelta(days, seconds, microseconds, milliseconds, minutes, hours, weeks)
t = Timer(days=2)
while(not t.isDone()):
#Do other game stuff here....
time_left = t.timeLeft()
print(f"time: {time_left}")
#And here....
print("Done now")
I have a python program I wrote that moves my solar panel with the sun throughout the day. It works fine, but about twice a week I get RecursionError: maximum recursion depth exceeded
I'm pretty new to python and I've looked up Recursion Errors, it says when a function calls itself too many times, I don't see where that is happening in this program.
from datetime import date
from datetime import datetime, timezone, timedelta
import astral
from astral import Astral
import time
import pytz
# import RPi.GPIO as GPIO
# Global Variables
ast = Astral()
city_Name = 'Cleveland'
local_City = ast[city_Name]
# sun_Position = local_City.sun(local=True)
reset_Solar = True
# Retrieves and returns current time
def get_Current_Time():
eastern = pytz.timezone('America/New_York')
curr_Time = datetime.now(eastern)
return curr_Time
def main_Function():
global local_City
sun_Position = local_City.sun(local=True)
current_Time = get_Current_Time()
solar_Sunrise = sun_Position.get('sunrise')
solar_Noon = sun_Position.get('noon')
solar_Sunset = sun_Position.get('sunset')
calc_Sunrise_Noon = solar_Noon - solar_Sunrise
total_Seconds = calc_Sunrise_Noon.seconds
calc_Hours, remainder = divmod(total_Seconds, 3600)
calc_Minutes, calc_Seconds = divmod(remainder, 60)
time_To_Adjust = total_Seconds / 24
print (current_Time)
print (solar_Sunrise)
if current_Time >= solar_Sunrise and current_Time < solar_Sunset:
solar_Adjust_Active(time_To_Adjust)
elif reset_Solar == True:
reset_Solar_Panel()
else:
solar_Adjust_Deactive()
def solar_Adjust_Active(time_To_Adjust):
while time_To_Adjust > 0:
current_Time = get_Current_Time()
time_To_Adjust = time_To_Adjust - 1
time.sleep(1)
print (current_Time)
print (time_To_Adjust)
daylight_Adjustment()
def solar_Adjust_Deactive():
global local_City
curr_Time = get_Current_Time()
calc_Tomorrow = curr_Time.date() + timedelta(days=1)
sun_Position_Tomorrow = local_City.sun(local=True, date = calc_Tomorrow)
solar_Sunrise_Tomorrow = sun_Position_Tomorrow.get('sunrise')
time_Till_Sunrise = solar_Sunrise_Tomorrow - curr_Time
sunrise_Total_Seconds = time_Till_Sunrise.seconds
calc_Sunrise_Hours, remainder = divmod(sunrise_Total_Seconds, 3600)
calc_Sunrise_Minutes, calc_Sunrise_Seconds = divmod(remainder, 60)
while sunrise_Total_Seconds > 0:
sunrise_Total_Seconds = sunrise_Total_Seconds - 1
time.sleep(1)
# print ('Seconds till Sunrise', sunrise_Total_Seconds)
print (solar_Sunrise_Tomorrow)
main_Function()
def daylight_Adjustment():
global reset_Solar
# Adustment to Solar Panel
#GPIO.setmode(GPIO.BCM)
# init pin numbers
#pin_Open = [6]
# set mode default state is 'low'
#GPIO.setup(pin_Open, GPIO.OUT)
# Activate Open Relay to High (High turns Relay on)
#GPIO.output(pin_Open, GPIO.HIGH) # Activate Open relay
# Start Timer for duration actuator will be activated
timer = 0
while timer < 1:
time.sleep(1)
timer = timer + 1
print ('Panal adjusted')
# set Open relay back to low (Turns Relay off)
#GPIO.output(pin_Open, GPIO.LOW)
# Reset GPIO settings
#GPIO.cleanup()
reset_Solar = True
main_Function()
def reset_Solar_Panel():
global reset_Solar
print ('Setting panel back to original position')
# Adustment to Solar Panel
# GPIO.setmode(GPIO.BCM)
# init pin numbers
# pin_Open = [XX]
# set mode default state is 'low'
# GPIO.setup(pin_Open, GPIO.OUT)
# Activate Open Relay to High (High turns Relay on)
# GPIO.output(pin_Open, GPIO.HIGH) # Activate Open relay
# Start Timer for duration actuator will be activated
timer = 0
while timer <= 48:
time.sleep(1)
timer = timer + 1
# set Open relay back to low (Turns Relay off)
# GPIO.output(pin_Open, GPIO.LOW)
# Reset GPIO settings
# GPIO.cleanup()
reset_Solar = False
main_Function()
main_Function()
You have (at least one) a loop in your code:
def main_Function():
-> solar_Adjust_Active(time_To_Adjust)
-> daylight_Adjustment()
-> main_Function() -> .... # lets run that for a couple of days ...
Normally you have a main loop (f.e. while True:) and call/return from functions into your main loop without recursing:
Pseudocode:
def resetToStart():
move panels to sunrise position
return
def movePanel():
get_currnt_optimal_position_for_datetime
move_to_that_position
return
resetToStart() # start at a well known position
while True:
if NightTime: # sun is down
resetToStart()
sleep till daytime
elif DayTime: # sun is up
movePanel()
sleep some till adjustment needed
import time
def timer():
now = time.localtime(time.time())
return now[5]
run = raw_input("Start? > ")
while run == "start":
minutes = 0
current_sec = timer()
#print current_sec
if current_sec == 59:
mins = minutes + 1
print ">>>>>>>>>>>>>>>>>>>>>", mins
I want to create a kind of stopwatch that when minutes reach 20 minutes, brings up a dialog box, The dialog box is not the problem. But my minutes variable does not increment in this code.
See Timer Objects from threading.
How about
from threading import Timer
def timeout():
print("Game over")
# duration is in seconds
t = Timer(20 * 60, timeout)
t.start()
# wait for time completion
t.join()
Should you want pass arguments to the timeout function, you can give them in the timer constructor:
def timeout(foo, bar=None):
print('The arguments were: foo: {}, bar: {}'.format(foo, bar))
t = Timer(20 * 60, timeout, args=['something'], kwargs={'bar': 'else'})
Or you can use functools.partial to create a bound function, or you can pass in an instance-bound method.
You can really simplify this whole program by using time.sleep:
import time
run = raw_input("Start? > ")
mins = 0
# Only run if the user types in "start"
if run == "start":
# Loop until we reach 20 minutes running
while mins != 20:
print(">>>>>>>>>>>>>>>>>>>>> {}".format(mins))
# Sleep for a minute
time.sleep(60)
# Increment the minute total
mins += 1
# Bring up the dialog box here
I'd use a timedelta object.
from datetime import datetime, timedelta
...
period = timedelta(minutes=1)
next_time = datetime.now() + period
minutes = 0
while run == 'start':
if next_time <= datetime.now():
minutes += 1
next_time += period
Your code's perfect except that you must do the following replacement:
minutes += 1 #instead of mins = minutes + 1
or
minutes = minutes + 1 #instead of mins = minutes + 1
but here's another solution to this problem:
def wait(time_in_seconds):
time.sleep(time_in_seconds) #here it would be 1200 seconds (20 mins)
mins = minutes + 1
should be
minutes = minutes + 1
Also,
minutes = 0
needs to be outside of the while loop.
I want to create a kind of stopwatch that when minutes reach 20 minutes, brings up a dialog box.
All you need is to sleep the specified time. time.sleep() takes seconds to sleep, so 20 * 60 is 20 minutes.
import time
run = raw_input("Start? > ")
time.sleep(20 * 60)
your_code_to_bring_up_dialog_box()
# this is kind of timer, stop after the input minute run out.
import time
min=int(input('>>'))
while min>0:
print min
time.sleep(60) # every minute
min-=1 # take one minute
import time
...
def stopwatch(mins):
# complete this whole code in some mins.
time.sleep(60*mins)
...
import time
mintt=input("How many seconds you want to time?:")
timer=int(mintt)
while (timer != 0 ):
timer=timer-1
time.sleep(1)
print(timer)
This work very good to time seconds.
You're probably looking for a Timer object: http://docs.python.org/2/library/threading.html#timer-objects
Try having your while loop like this:
minutes = 0
while run == "start":
current_sec = timer()
#print current_sec
if current_sec == 59:
minutes = minutes + 1
print ">>>>>>>>>>>>>>>>>>>>>", mins
import time
def timer(n):
while n!=0:
n=n-1
time.sleep(n)#time.sleep(seconds) #here you can mention seconds according to your requirement.
print "00 : ",n
timer(30) #here you can change n according to your requirement.
import time
def timer():
now = time.localtime(time.time())
return now[5]
run = raw_input("Start? > ")
while run == "start":
minutes = 0
current_sec = timer()
#print current_sec
if current_sec == 59:
mins = minutes + 1
print ">>>>>>>>>>>>>>>>>>>>>", mins
I was actually looking for a timer myself and your code seems to work, the probable reason for your minutes not being counted is that when you say that
minutes = 0
and then
mins = minutes + 1
it is the same as saying
mins = 0 + 1
I'm betting that every time you print mins it shows you "1" because of what i just explained, "0+1" will always result in "1".
What you have to do first is place your
minutes = 0
declaration outside of your while loop. After that you can delete the
mins = minutes + 1
line because you don't really need another variable in this case, just replace it with
minutes = minutes + 1
That way minutes will start off with a value of "0", receive the new value of "0+1", receive the new value of "1+1", receive the new value of "2+1", etc.
I realize that a lot of people answered it already but i thought it would help out more, learning wise, if you could see where you made a mistake and try to fix it.Hope it helped. Also, thanks for the timer.
from datetime import datetime
now=datetime.now()
Sec=-1
sec=now.strftime("%S")
SEC=0
while True:
SEC=int(SEC)
sec=int(sec)
now=datetime.now()
sec=now.strftime("%S")
if SEC<sec:
Sec+=1
SEC=sec
print(Sec) #the timer is Sec