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.
Related
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:
I am running a Python Tkinter GUI application for multiple days (ideally it will run continuously without needing to be restarted). After a few days, the program typically crashes with no explanation or error messages. I have used cProfile to profile the animation functionality of our Matplotlib graphs and search for possible slow-down points. The results clearly showed that the only function which increased in execution time over the program run period was this one:
/usr/lib/python3/dist-packages/matplotlib/transforms.py:134(_invalidate_internal)
I've looked at the Matplotlib source code (https://github.com/matplotlib/matplotlib/blob/main/lib/matplotlib/transforms.py), but I haven't been able to figure out what this function is doing. What does _invalidate_internal do, and is there anything I can do to prevent it from taking so long to execute?
For more context, our program has several animated matplotlib plots which graph inputs from sensor data over time. We plot the n most recent data points on each frame so that it gives the effect of a scrolling graph. Here is the animation code:
def animate(ii):
while True:
most_recent_time_graphed = param_dict[param_list[0]] #first, pulls up first plot
most_recent = reader.query_by_num(table="SensorData", num=1)
reader.commit() #if identical, do not animate
#then checks that plot's time list
if (len(most_recent) == 0):
break
#time_reader = datetime.strptime(most_recent[0][0], "%m/%d/%Y %H:%M:%S")
time_reader = datetime.datetime.fromtimestamp(most_recent[0][0])
if (len(most_recent_time_graphed.tList) != 0) and (time_reader == most_recent_time_graphed.tList[0]):
for i, param in enumerate(param_list, 1):
current_text = live_dict[param]
current_text.label.config(text=most_recent[0][i], fg="black", bg="white")
break #checks if the timestamp is exactly the same as prior, i.e. no new data points have been logged in this frame
#do I have to add an else?
else:
config_settings = csv_read()
c0, c1, c2 = config_dict['enable_text'], config_dict['num_config'], config_dict['provider_config']
c3, c4, c5 = config_dict['email_config'], config_dict['upper_config'], config_dict['lower_config']
for i, key in enumerate(param_dict, 1):
current_plot = param_dict[key]
current_param_val = float(most_recent[0][i])
current_text = live_dict[key] #update to live text data summary
if current_param_val > float(config_settings[c4][i-1]) or current_param_val < float(config_settings[c5][i-1]):
#only send text if enable_text is True
if config_settings[c0] == [str(True)]:
###sends text if new problem arises or every 5 minutes
if allIsGood[key] and Minute[key] == None:
print('new problem')
Minute[key] = datetime.now().minute
minuta[key] = Minute[key]
pCheck(float(config_settings[c4][i-1]),float(config_settings[c5][i-1]),key,current_param_val,config_settings[c1],config_settings[c2]) #uncomment to test emergency texts
elif allIsGood[key] == False and abs(Minute[key] - datetime.now().minute) % 5 == 0 and not (minuta[key] == datetime.now().minute):
print('same problem')
minuta[key] = datetime.now().minute
pCheck(float(config_settings[c4][i-1]),float(config_settings[c5][i-1]),key,current_param_val,config_settings[c1],config_settings[c2]) #uncomment to test emergency texts
#pass
#setting the parameter to not ok
allIsGood[key] = False
current_text.label.config(text=most_recent[0][i], fg="red", bg="white")
current_plot.plot_color = 'r'
else:
current_text.label.config(text=most_recent[0][i], fg="black", bg="white")
current_plot.plot_color = 'g'
###setting the parameter back to true and sending "ok" text
if allIsGood[key] == False:
Minute[key] = None
allOk(key,config_settings[c1],config_settings[c2])
pass
allIsGood[key] = True
data_stream = current_plot.incoming_data
time_stream = current_plot.tList
data_stream.insert(0, most_recent[0][i])
#time_f = datetime.strptime(most_recent[0][0], "%m/%d/%Y %H:%M:%S")
time_f = datetime.datetime.fromtimestamp(most_recent[0][0])
time_stream.insert(0, time_f)
if len(data_stream) < 20: #graph updates, growing to show 20 points
current_plot.make_plot()
else: #there are 20 points and more available, so animation occurs
data_stream.pop()
time_stream.pop()
current_plot.make_plot()
break
The current "time_elapsed" duration appears as text in the tkinter window, but doesn't update like a timer. I can only assume I'm missing an important method that would allow the duration to update. I'm sure the answer is simple and I'm just looking too deeply into it. Any suggestions?
from tkinter import *
import datetime, time
root = Tk()
root.title("Debut Date")
root.geometry("600x400")
root.config(bg="#000000")
#date/time of first post (August 21, 6:30:54pm):
Year = 2020
Month = 8
Day = 21
Hour = 18
Minute = 30
Second = 54
DOP = datetime.datetime(Year,Month,Day,Hour,Minute,Second) #DOP represents "Date of Post" and
is defined by "Year", "Month", "Day", "Hour", "Minute", & "Second"
DSP = (datetime.datetime.now() - DOP) #DSP represents "Duration Since Post" and is defined by
datetime.now() minus "Date of Post"
duration = DSP.total_seconds() #total number of seconds between DOP and DSP
years = divmod(duration, 31536000)
days = divmod(years[1], 86400) #uses remainder of years to calculate days
hours = divmod(days[1], 3600) #uses remainder of days to calculate hours
minutes = divmod(hours[1], 60) #uses remainder of hours to calculate minutes
seconds = divmod(minutes[1], 1) #uses remainder of minutes to calculate seconds
def update_time():
time_elapsed = ("%d:%d:%d:%d:%d" % (years[0], days[0], hours[0], minutes[0], seconds[0]))
label.config(text = time_elapsed)
label.after(1000, update_time)
label = Label(root, text="", font=("Helvetica", 50), fg="#ffffff", bg="#000000", bd=50)
label.pack()
update_time()
root.mainloop()
Your update_time has three critical flaws. For one, it calls itself both with after and also directly. The call to update_time() causes an infinite loop.
The second problem is that you're calling root.mainloop() inside of update_time. The vast majority of time, you should only ever call mainloop() a single time during the life of your program.
The third problem is that each time update_time is called it creates a new label. You should be creating the label only once, so you need to move the creation of the label to outside of the function. You can update the label by calling the configure method to change the text option.
Try this:
from tkinter import *
import datetime, time
root = Tk()
root.title("Debut Date")
root.geometry("600x400")
root.config(bg="#000000")
#date/time of first post (August 21, 6:30:54pm):
Year = 2020
Month = 8
Day = 21
Hour = 18
Minute = 30
Second = 54
DOP = datetime.datetime(Year,Month,Day,Hour,Minute,Second) #DOP represents "Date of Post" and is defined by "Year", "Month", "Day", "Hour", "Minute", & "Second"
def update_time():
DSP = (datetime.datetime.now() - DOP) #DSP represents "Duration Since Post" and is defined by datetime.now() minus "Date of Post"
duration = DSP.total_seconds() #total number of seconds between DOP and DSP
years = divmod(duration, 31536000)
days = divmod(years[1], 86400) #uses remainder of years to calculate days
hours = divmod(days[1], 3600) #uses remainder of days to calculate hours
minutes = divmod(hours[1], 60) #uses remainder of hours to calculate minutes
seconds = divmod(minutes[1], 1) #uses remainder of minutes to calculate seconds
time_elapsed = ("%d:%d:%d:%d:%d" % (years[0], days[0], hours[0], minutes[0], seconds[0]))
label.config(text = time_elapsed)
label.after(1000, update_time)
label = Label(root, text="", font=("Helvetica", 50), fg="#ffffff", bg="#000000", bd=50)
label.pack()
update_time()
root.mainloop()
Like I pointed out in the comment:
You need to move everything after (including the) label = Label(...) outside of the function.
You also need to update your variables each time the function is called.
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
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