Getting invalid command name in my Tkinter app - python
When I run my application , its supposed to play an mp3 file when the current time is equal to one of times in a list. The mp3 file is in the same folder as my python file. However, Three things happen. First, the sound doesn't play even though the time is correct and an output is shown in the terminal indicating that the time comparison is true. Second, an extra tkinter window pops up and finally, when I try to close both of the windows, I get these errors:
time to pray at 03:10 PM
invalid command name "2184036301640calc_countdown"
while executing
"2184036301640calc_countdown"
("after" script)
Traceback (most recent call last):
File "d:\My stuff\mypython\Tkinter\azan caller\azan_caller.py", line 266, in <module>
call_azan()
File "d:\My stuff\mypython\Tkinter\azan caller\azan_caller.py", line 152, in call_azan
playsound(azan_path)
File "C:\Users\rahma\AppData\Local\Programs\Python\Python37\lib\site-packages\playsound.py", line 17, in _playsoundWin
from random import random
ImportError: cannot import name 'random' from 'random' (d:\My stuff\mypython\Tkinter\azan caller\random.py)
Random.py is another file in the folder but I never used it in my main python file. This is my full code just for completeness:
import tkinter as tk
from tkinter import Grid
import xlrd
import os
from xlrd import cellname,xldate_as_tuple,xldate_as_datetime
from datetime import date
from datetime import datetime , timedelta
from playsound import playsound
from tkinter import font
#set time and current date
current_time = datetime.strftime(datetime.now(), "%I:%M %p") #time.strftime("%I:%M %p")
todays_date = date.today()
month = todays_date.strftime('%m')
def current_date(todays_date):
format_date = todays_date.strftime("%d/%m/%Y")
return format_date
format_date = current_date(todays_date)
#function to display current time
def display_time():
current_time = datetime.strftime(datetime.now(), "%I:%M %S %p")
lbl_display_time.config(text=current_time)
lbl_display_time.after(1000,display_time)
#function to display current date
def display_date():
todays_date = date.today()
month = todays_date.strftime('%m')
format_date = todays_date.strftime("%d/%m/%Y")
lbl_display_date.config(text=format_date)
lbl_display_date.after(1000,display_date)
#open workbook
filename = os.path.join("D:\My stuff\mypython\Tkinter",'azan caller\prayer_timings.xlsx')
workbook = xlrd.open_workbook(filename)
worksheet = workbook.sheet_by_name('Sheet %s'% month)
def get_date(format_date):
#number of rows in sheet
rows = worksheet.nrows
#get date from excel file and compare with current date
raw_date = ''
for i in range(-1,rows):
raw_date = worksheet.cell_value(i,1)
conv_date = datetime(*xlrd.xldate_as_tuple(raw_date, workbook.datemode))
excel_date = conv_date.strftime("%d/%m/%Y")
if format_date == excel_date:
cell_location = (i,1)
break
return [cell_location , excel_date]
def calc_countdown():
''' This function calculates the remaining time before the next prayer '''
#converts prayer times to datetime object
struc_prayertime_list = [datetime.strptime(i, "%I:%M %p") for i in azan_time]
#gets the current time and converts it to datetime object
current_time = datetime.strptime(datetime.strftime(datetime.now(), "%I:%M:%S %p"), "%I:%M:%S %p")
#gets the next prayer time
nearest_time = next((i for i in struc_prayertime_list if i > current_time), datetime.strptime('01-02 04:18 AM', "%m-%d %I:%M %p"))
#calculates the time left before next prayer, converts it to string and stores it in a variable
time_left_text.set("{} hours {} minutes {} seconds".format(*str(nearest_time - current_time).split(":")))
random_lbl.after(1000, calc_countdown)
#get time for different prayers
def fajr_time(cell_location):
fajr = worksheet.cell_value(cell_location[0][0],3)
return fajr
def zuhr_time(cell_location):
zuhr = worksheet.cell_value(cell_location[0][0],5)
return zuhr
def asr_time(cell_location):
asr = worksheet.cell_value(cell_location[0][0],6)
return asr
def maghrib_time(cell_location):
maghrib = worksheet.cell_value(cell_location[0][0],7)
return maghrib
def isha_time(cell_location):
isha = worksheet.cell_value(cell_location[0][0],8)
return isha
def update_time():
''' this function will run continuoulsy and its function is to keep updating the prayer times
as the day and date changes flow : get the correct cell_location using get_Date() --- set prayer times
using cell_location --- append prayer times(variables) to a list called azan_time--- return azan_time '''
cell_location = get_date(format_date)
#set prayer times
fajr = fajr_time(cell_location)
fajr="0"+fajr
zuhr = zuhr_time(cell_location)
asr = asr_time(cell_location)
maghrib = maghrib_time(cell_location)
isha = isha_time(cell_location)
#store prayer times in a list
azan_time = [fajr,zuhr,asr,maghrib,isha,"3:10 PM"]
#checks if any of the time is in PM. IF so, a '0' is added to the beginning
azan_time.remove(zuhr) #temporarily remove zuhr time
for x in range(0,len(azan_time)):
temp_time = azan_time[x]
if temp_time[-2]+temp_time[-1] == 'PM':
azan_time[x] = '0'+azan_time[x]
azan_time.insert(1,zuhr) # add zuhr time back
random_lbl.after(1000,update_time)
return azan_time #return azan time so it can be used
#function to check if it is time for prayer
def call_azan():
current_time = datetime.strftime(datetime.now(), "%I:%M %p")
for i in range(0,len(azan_time)):
if current_time == azan_time[i]:
print("time to pray at" , azan_time[i])
azan_path = os.path.join("azan caller","azan_sound.mp3")
playsound(azan_path)
else:
continue
random_lbl.after(1000,call_azan)
#GUI
window = tk.Tk()
window.title("Azan Caller")
Grid.rowconfigure(window, 0, weight=1)
Grid.columnconfigure(window, 0, weight=1)
#set up window
height = window.winfo_screenheight()
width = window.winfo_screenwidth()
window.geometry(f'{int(width/2)}x{int(height/2)}')
frm_window = tk.Frame(window,bg="#00BFFF")
frm_window.pack(fill="both",expand=True)
# a label just to run the functions continuously after 1 second
random_lbl = tk.Label(frm_window,width=2)
#create fonts
heading_font = font.Font(family = "ShareTech",size=25,weight='bold')
subheading_font = font.Font(family="ShareTech",size=14)
body_font = font.Font(family="ShareTech",size=10,weight="bold")
# title section
frm_title = tk.Frame(frm_window,relief=tk.SOLID,borderwidth=3,bg="#000000")
frm_title.grid(row=0, column=0, sticky="new",pady=(0,5))
lbl_title = tk.Label(master=frm_title, text="Azan Caller For Abu Dhabi",font=heading_font,fg="#008000")
lbl_title.pack(side='top',fill='x')
#prayer timings table
frm_table = tk.Frame(frm_window,bg="#000000",relief=tk.SOLID,borderwidth=3)
frm_table.grid(row=1,column=0, sticky="nsew",padx=(20,20))
tbl_title = tk.Label(frm_table,text="Today's Prayer Times",relief=tk.SOLID,font=subheading_font,borderwidth=2)
tbl_title.grid(row=0,column=0,columnspan=5,sticky="nsew")
#prayer names
prayer_names = ['Fajr','Zuhr','Asr','Maghrib','Isha']
for j in range(0,len(prayer_names)):
name = prayer_names[j]
cell = tk.Label(frm_table,text=name,relief=tk.SOLID,font=body_font,borderwidth=2)
cell.grid(row=1,column=j,sticky="nsew")
#prayer times
azan_time = update_time()
for i in range(0,len(azan_time)):
prayer_time = azan_time[i]
cell_time = tk.Label(frm_table,text=prayer_time,relief=tk.SOLID,font=body_font,borderwidth=2,fg="#FF8C00")
cell_time.grid(row=2,column=i,sticky="nsew")
#body section
frm_body = tk.Frame(frm_window,relief=tk.SOLID,borderwidth=5,)
frm_body.grid(row=2, column=0, sticky="nsew",pady=(10,10),padx=(20,20))
lbl_date = tk.Label(frm_body,text="Today's Date: ",font=body_font)
lbl_date.grid(row=0,column=0,sticky="nsew",pady=(0,5))
lbl_display_date = tk.Label(frm_body,font=body_font)
lbl_display_date.grid(row=0,column=1,sticky="nsew",pady=(0,5))
lbl_time = tk.Label(frm_body,text="Current Time: ",font=body_font)
lbl_time.grid(row=1,column=0,sticky="nsew",pady=(0,5))
lbl_display_time = tk.Label(frm_body,font=body_font)
lbl_display_time.grid(row=1,column=1,sticky="nsew",pady=(0,5))
time_left_text = tk.StringVar()
lbl_countdown = tk.Label(frm_body,text="Next Prayer in : ",font=body_font)
lbl_countdown.grid(row=2,column=0,sticky="nsew",pady=(0,5))
lbl_display_countdown = tk.Label(frm_body,textvariable=time_left_text,font=body_font,fg="red")
lbl_display_countdown.grid(row=2,column=1,sticky="nsew",pady=(0,5))
#footer
frm_footer = tk.Frame(frm_window,relief=tk.SOLID,borderwidth=3,bg="#000000")
frm_footer.grid(row=3, column=0, sticky="sew",pady=(10,0))
lbl_footer = tk.Label(frm_footer,text="#Copyright AbdulRahman Tijani 2020",font=body_font,fg="#008000")
lbl_footer.pack(side="bottom",fill='x')
#make the structure resizable
#columns
for i in range(frm_window.grid_size()[0]):
frm_window.grid_columnconfigure(i, weight=1)
for i in range(frm_table.grid_size()[0]):
frm_table.grid_columnconfigure(i, weight=1)
for i in range(frm_body.grid_size()[0]):
frm_body.grid_columnconfigure(i,weight=1)
#row
for i in range(frm_window.grid_size()[1]):
frm_window.grid_rowconfigure(i, weight=1)
for i in range(frm_table.grid_size()[1]):
frm_table.grid_rowconfigure(i, weight=1)
for i in range(frm_body.grid_size()[1]):
frm_body.grid_rowconfigure(i,weight=1)
#run functions
display_date()
display_time()
update_time()
call_azan()
calc_countdown()
window.mainloop()
Thank you in Advance
The problem here is because you have a file in your directory called random.py which is being imported here and python is reading that in and not the random module, so try not to name your script files as same as the module names.
And instead of using playsound, why dont you try the pygame module for playing sounds. Refer how to here
Related
Python script I want run loop when system time 30 second
I want to run the loop only when the actual system time has 30 seconds mark and then onwards every iteration happens after 1 minute. import pandas as pd from datetime import datetime df = pd. read_excel('data.xlsx') Time30 = now.replace(hour=00, minute=00, second=30) for i in df.index: entry = df.loc[i] now = datetime.now() current_time = now.strptime('%S') current_time == Time30 name_input = browser.find_element_by_name('fullname') password_input = browser.find_element_by_name('password") `````````
How to put in if statement date format for entry in tkinter?
def Verification(): date_format = "%d/%m/%Y" if (datetime.strptime("1/1/2001", date_format) <= date_ < datetime.strptime("31/1/2008", date_format)): print('bravo') date_= datetime.strptime(date_,date_format) vt=date_ vt =StringVar() vt.set('') lb = Label(parent, text = 'birth day: ') cp = Entry(parent, textvariable=vt) bt = Button(parent, text ='Verify', command = Verification) lb.place(x=30, y=90) cp.place(x=95, y=90) bt.place(x=220,y=90)
I'm not sure I understand your question, so the following is an answer based on what I think you're asking. It works like this: When the Verify button is pressed the verification() function will be called which will initially attempt to parse what the user inputted into a datetime instance. If it cannot do that a error message indicating that will appear. If it succeeds then it next checks to see if it's in the required date range. Again, displaying an error message if it isn't. from datetime import datetime from tkinter import * import tkinter.messagebox as messagebox DATE_FORMAT = "%d/%m/%Y" MIN_DATE = datetime.strptime('1/1/2001', DATE_FORMAT) MAX_DATE = datetime.strptime('31/1/2008', DATE_FORMAT) def verification(): try: date_= datetime.strptime(vt.get(), DATE_FORMAT) except ValueError: messagebox.showerror('Invalid Date', f'"{vt.get()}"') return if MIN_DATE <= date_ < MAX_DATE: # Check date range. messagebox.showinfo('Bravo', "You entered a valid date!") else: messagebox.showerror('Out of range', vt.get()) parent = Tk() parent.geometry('300x200') vt = StringVar(value='D/M/Y') # Initially show required format. lb = Label(parent, text='birth day: ') cp = Entry(parent, textvariable=vt) bt = Button(parent, text ='Verify', command=verification) lb.place(x=30, y=90) cp.place(x=95, y=90) bt.place(x=220,y=90) parent.mainloop() Screenshot of it running:
Index Error, countdown calendar not working
Can you help me with my code? I wanted an if-else statement, that if there is no description for the festival is given, it displays there is no info about that particular festival. But for that, I would have to do if not(event[2]) but for that, it shows Traceback (most recent call last): File "C:\Users\kanav_i4cko4c\Downloads\My first tkinter program.py", line 52, in <module> if (event[2]): IndexError: list index out of range Here is the source code for festivals.txt Diwali,5/11/21 Christmas,25/12/21 Here is the source code for the main program from tkinter import Tk, Canvas, simpledialog, messagebox from datetime import date, datetime # function get_events is to get the celebration events def get_events(): list_events = [] with open('festivals.txt') as file: for line in file: line1 = line.rstrip('\n') global current_event current_event = line1.split(',') print('Check 0') print(current_event) current_event[1] = datetime.strptime(current_event[1], '%d/%m/%y').date() list_events.append(current_event) return list_events def days_between_dates(date1, date2): time_between = str(date1 - date2) number_of_days = time_between.split(' ') return number_of_days[0] # End of Functions # ----------------------------------------------------------------------------------------------- # Main program starts here root = Tk() root.title('Calendar') c = Canvas(root, width=2000, height=800, bg='dark blue') c.pack() c.create_text(100, 50, anchor='w', fill='white', font=' Times 40 bold underline', text='My Countdown Calendar') c.create_rectangle(30, 10, 60, 1000, outline="#fb0", fill="#fb0") events = get_events() today = date.today() # Make a dictionary for the festivals vertical_space = 100 events.sort(key=lambda x: x[1]) horizontal_space = 100 for event in events: event_name = event[0] days_until = days_between_dates(event[1], today) if (event[2]): display = 'It is %s days until %s. %s = %s' % (days_until, event_name, event_name,event[2]) else: display = 'It is %s days until %s. There is no info on %s' % (days_until, event_name, event_name) if (int(days_until) <= 50): text_col = '#c11a2b' else: text_col = 'SkyBlue1' c.create_text(100, vertical_space, anchor='w', fill=text_col, font='Calibri 28 bold', text=display) vertical_space = vertical_space + 30 horizontal_space = horizontal_space + 40
When you evaluate event[2] it attempts to retrieve the 3rd item in the list which isn't there so python raises an exception. One solution could be by initializing your list with default values: event = [None for i in range(3)] This way there is a None value at event[2] which can be evaluated by your if statement. Another solution could be to simply check whether the list contains less than 3 items: if len(event) <= 2: # do something
Tkinter python index
I was making a countdown calendar that checks how many days left, name and info, but it is the condition that changes the colour for if more than 50 days part that doesn't work. Can you guys check it?. It checks how many left for each festival. Also as u can see If I change the date to today of any festival, it shows 1 Day left until. I want to fix that Here is the text from festivals.txt Dashain,14/10/21,This is Nepal Main Festival Tihar,6/11/21,Festival of Lights Christmas,25/12/21,Jingle Bells New Year,1/01/22,The Day of the new year from tkinter import Tk, Canvas, simpledialog, messagebox from datetime import date, datetime # function get_events is to get the celebration events def get_events(): list_events = [] with open('festivals.txt') as file: for line in file: line1 = line.rstrip('\n') global current_event current_event = line1.split(',') current_event[1] = datetime.strptime(current_event[1], '%d/%m/%y').date() list_events.append(current_event) return list_events # Function to get the dates between the 2 def days_between_dates(date1, date2): time_between = str(date1 - date2) number_of_days = time_between.split(' ') return number_of_days[0] # End of Functions # ----------------------------------------------------------------------------------------------- # Main program starts here root = Tk() root.title('Calendar') # Make Canvas c = Canvas(root, width=2000, height=800, bg='black') c.pack() c.create_text(100, 50, anchor='w', fill='cyan', font=' Times 40 bold italic underline', text='My Countdown Calendar' ) # Store the functions in variables events = get_events() today = date.today() # Aligning the text, sorting the list vertical_space = 100 events.sort(key=lambda x: x[1]) horizontal_space = 100 # Main Loop for event in events: event_name = event[0] days_until = days_between_dates(event[1], today) display = 'It is %s days until %s. %s is about %s' % (days_until, event_name, event_name,event[2]) if (int(days_until) > 10): text_col = '#c11a2b' remin = 'Come one %s in coming' % (event_name) c.create_text(550, 500, anchor='w', fill='purple', font='Courier 20 bold underline', text=remin) else: text_col = 'lime' c.create_text(200, vertical_space, anchor='w', fill=text_col, font='Calibri 28 bold', text=display) vertical_space = vertical_space + 30 horizontal_space = horizontal_space + 40
There are a couple of problems with the date calculations. Firstly you can obtain the number of days using the days attribute of the timedelta object returned by date1 - date2 in days_between_dates(). That function could be written as: def days_between_dates(date1, date2): return (date1 - date2).days This is more succinct and less error prone, and now it will return an integer that is more useful in other calculations. This also fixes a bug. When the dates are the same and str(date1 - date2) returns '0:00:00' which your code fails to parse. Regarding the greater than 50 condition, there is no such check in your code. There is a > 10 but your test data does not test that condition. You should add a line with a date within 10 days of the current day. Finally you will need to handle past events for when the event has already happened. Currently the fixed code would display a negative number of days until the event.
if date is weekend - auto rerun the function
So I can generate random days in a given start-end date relationship, but, if the date happens to be a weekend - currently all I can get working is to print to the user 'it is a weekend'. What I would like to do is, if the random day IS a weekend, rerun the function so the user does not have to manually. Basically - only print out weekdays - currently, if the random day is a weekend, it prints a blank space or None value. Only return/print weekdays is the main goal. Here is the code so far: from datetime import datetime, timedelta from random import randrange def random_date(start, end): delta = end - start random_day = randrange(delta.days) myresult = start + timedelta(days=random_day) return myresult d1 = datetime.strptime('9/1/2018', '%m/%d/%Y') d2 = datetime.strptime('9/30/2018', '%m/%d/%Y') myresult = random_date(d1, d2) if myresult.weekday() not in (5, 6): print myresult.strftime('%m-%d-%Y') else: print "hit a weekend"
An option: def random_weekday(start, end): date = None while (not date or date.weekday() in (5, 6)): days = randrange((end - start).days) date = start + timedelta(days=days) return date start = datetime.strptime('9/1/2018', '%m/%d/%Y') end = datetime.strptime('9/30/2018', '%m/%d/%Y') for i in range(20): print(random_weekday(start, end).strftime('%m-%d-%Y'))
So, you need a while-loop to keep getting dates until you get one that's not a weekend, like this: from datetime import datetime from random import randrange from datetime import timedelta def random_date(start, end): delta = end - start random_day = randrange(delta.days) myresult = start + timedelta(days=random_day) return myresult while True: d1 = datetime.strptime('9/1/2018', '%m/%d/%Y') d2 = datetime.strptime('9/30/2018', '%m/%d/%Y') myresult = random_date(d1, d2) if myresult.weekday() not in (5,6): break print myresult.strftime('%m-%d-%Y')