I had a big data analysis script based on Monte Carlo simulations and wanted to try to use a GUI for it.
At the moment I have a window (will label better later) that allows the user to enter the desired type of card, number of months and how many packs are open per month. The program then makes a prediction on how many cards of that type would the user have after those months.
For now, I have the program print the result out once the start button is pressed to run it and the window is closed to end the tkinter loop. The goal would be that once the start button is pressed, a new window would open with the result.
However, after the result is printed, the window either freezes completely or closes but the icon still appears loading. My guess is that something is going on with the thread that prevents it from ending once the main loop ends. When I quit, I get this message:
Fatal Python error: PyEval_RestoreThread: the function must be called with the GIL held, but the GIL is released (the current Python thread state is NULL)
Python runtime state: initialized
Here is the full script:
#This is a Python code
#I have been doing this in my work breaks, so don't take it as fully finished
import numpy as np
import python_settings as st
from tkinter import *
from tkinter import ttk
import threading
#I am considering that a person opens 3 packs of 9 cards each every month.
win = Tk() #Create an instance of tkinter frame or window
canvas1 = Canvas(win, width=400, height=200, relief='raised')
canvas1.pack()
#Create a label
label=Label(win, text= "What type of card?",
borderwidth=0, font=('Aerial 20 bold'), fg='HotPink4')
label.configure(font=('helvetica', 14))
canvas1.create_window(200, 25, window=label)
name = StringVar()
n_packs_month = IntVar()
n_packs_month.set('0')
n_months= IntVar()
n_months.set('00')
entry1 = ttk.Entry(win, width=3, font=("Arial",18,""), textvariable = n_packs_month)
entry1.config(foreground='pink')
entry2 = ttk.Entry(win, width=3, font=("Arial",18,""), textvariable = n_months)
entry2.config(foreground='pink')
entry3 = ttk.Entry(win, width=7, font=("Arial",18,""), textvariable = name)
entry3.config(foreground='pink')
canvas1.create_window(260, 100, window=entry1)
canvas1.create_window(210, 100, window=entry2)
canvas1.create_window(100, 100, window=entry3)
#x = input('What type of card? The rarities are common, rare, super, ultra, secret, ultimate or ghost. ')
total_cards = 9
n_people = 1000
def play_yg(): #possabilities when opening yugioh packs
common_prob = (8/9) #1728
super_prob = (1/54) #36
ultra_prob = (1/108) #18
secret_prob = (1/216) #9
ultimate_prob = (1/432) #4.5
ghost_prob = (1/1944)
rare_prob = 1- (common_prob + super_prob + ultra_prob + secret_prob + ultimate_prob + ghost_prob)
possible_outcomes = ['common', 'rare', 'super', 'ultra', 'secret', 'ultimate', 'ghost']
probabilities = [common_prob, rare_prob, super_prob, ultra_prob, secret_prob, ultimate_prob, ghost_prob]
outcome = np.random.choice(possible_outcomes,total_cards, p=probabilities)
return outcome
def perform_simulation(): #simulation of one person opening packs
n_times = int(n_packs_month.get()) * int(n_months.get())
common = 0
rare = 0
superc = 0
ultra = 0
secret = 0
ultimate = 0
ghost = 0
results = np.empty(9, dtype = str)
for n in range(n_times):
outcome = play_yg()
results = np.vstack((results, outcome))
common = round(np.count_nonzero(results == 'common'),0)
rare = round(np.count_nonzero(results == 'rare'), 0)
superc = round(np.count_nonzero(results == 'super'), 0)
ultra = round(np.count_nonzero(results == 'ultra'), 0)
secret = round(np.count_nonzero(results == 'secret'), 0)
ultimate = round(np.count_nonzero(results == 'ultimate'), 0)
ghost = round(np.count_nonzero(results == 'ghost'),0)
return common, rare, superc, ultra, secret, ultimate, ghost, n_times
list1 = []
def everyone(): # simulation of a bunch of people opening packs and averaging their outcomes
receive = 0
results = 0
x = name.get()
for n in range(n_people):
if x == 'common':
receive = perform_simulation()[0]
elif x == 'rare':
receive = perform_simulation()[1]
elif x == 'super':
receive = perform_simulation()[2]
elif x == 'ultra':
receive = perform_simulation()[3]
elif x == 'secret':
receive = perform_simulation()[4]
elif x == 'ultimate':
receive = perform_simulation()[5]
elif x == 'ghost':
receive = perform_simulation()[6]
results = results + receive
mean = np.around(results/(n+1), 0)
list1.append(mean)
return mean, x
def start_everyone_in_bg():
threading.Thread(target=everyone).start()
button2 = ttk.Button(win, text = 'Start', command= lambda: [play_yg(), perform_simulation(), start_everyone_in_bg(),])
canvas1.create_window(200, 180, window=button2)
win.mainloop()
print(everyone())
So I tried using Event but the problem remained. I did some research on the error and there's not much information on it. Some people suggested it might be a memory problem with the python version.
Any ideas on an easy fix? I'm using Python 3.9.12 on macOS Big Sur.
Thanks in advance :)