#python #tkinter #pyinstaller #exe
#python #tkinter #pyinstaller #exe
Вопрос:
Итак, я создал своего рода калькулятор с использованием tkinter и сделал так, чтобы быстрая настройка создавала файл save.dat в каталоге AppData, и это работает как скрипт python, однако при компиляции с использованием строки:
pyinstaller --onefile -w file.py
это не работает. Процесс exe
установки выполняется просто отлично, но, похоже, после некоторого тестирования, когда он достигает конца инструкции if, если save.dat уже существует (появляется диалоговое окно, в котором есть флажок не показывать снова и кнопка OK), он не ожидает ответаи завершает работу. Я получаю представление об этом как о фоновом процессе, когда проверяю taskmanager, но окно никогда не появляется. Я не понимаю, в чем проблема, поэтому мне может понадобиться помощь. Вот фрагмент моего кода:
from tkinter import *
from tkinter import messagebox
import pickle
import os.path
import sys
def saving():
messagebox.showinfo("Setting Up", "Setup will now begin")
path = os.path.expanduser("~/AppData/Local")
os.chdir(path)
os.makedirs("hydrocalc")
loc = os.path.expanduser("~/AppData/Local/hydrocalc/save.dat")
new = "0"
pickle.dump(new, open(loc, "wb"))
popup = Tk()
popup.withdraw()
loc = os.path.expanduser("~/AppData/Local/hydrocalc/save.dat")
if (os.path.exists(loc)):
i = pickle.load(open(loc, "rb"))
# then a few variables referring to the calculator
def world():
#the functions referring to the calculator
if (i == "0"):
popup.deiconify()
popup["bg"] = "#f0f0f0"
popup.title("INSTRUCTIONS")
labelpu = Label(popup, bg="white", text= #instructions on usage, justify="left").grid()
popup.resizable(width=False, height=False)
var = StringVar()
check = Checkbutton(popup, text="Don't Show Again", variable=var, onvalue="1", offvalue="0",
bg="#f0f0f0")
check.deselect()
check.grid()
lbl = Label(popup, text=var.get())
def btnOkay():
global i
lbl = Label(popup, text=var.get())
if (var.get() == "0"):
popup.withdraw()
i = "1"
calc.deiconify()
world()
elif (var.get() == "1"):
info = open(loc, 'w ')
new = "1"
pickle.dump(new, open(loc, "wb"))
popup.withdraw()
calc.deiconify()
i = "1"
world()
popup.deiconify()
btnOK = Button(popup, text="OK", bg="#f0f0f0", justify="center", width=20,
command=lambda:btnOkay()).grid()
elif (i == "1"):
calc.deiconify()
world()
else:
saving()
messagebox.showinfo("Setup Complete", "Setup is now complete. Please restart the program to
continue.")
sys.exit()
Комментарии:
1. Попробуйте
pyinstaller -F -c file.py
зафиксировать ошибку на терминале и обновить вопрос с этим,2. Я попробовал это, и он открывает пустой терминал, запускает функцию сохранения (после того, как я удалил файл из моих предыдущих тестов), а затем, когда я запускаю его снова, еще один пустой терминал на несколько секунд, а затем он закрывается. Я использую Windows 10, но я не думаю, что это должно быть проблемой.
3. Он закрывается из-за
else
условия, верно? Что в этом плохого.4. я провел тест, в котором я помещал окно сообщения после каждой строки кода для отображения строки, и когда это вынуждает его замедляться, это показывает, что после его «отображения» (это должно быть настолько быстро, что экран даже не регистрирует его, потому что я никогда не видел его без строки).окна сообщений) кнопка (btnOK) просто отключается. оператор else работает отлично, просто он отказывается позволить мне нажать кнопку
5. Попробуйте заменить
sys.exit()
наpopup.destroy()
?
Ответ №1:
Необходимо внести несколько изменений, см. Обновленный код ниже
from tkinter import *
from tkinter import messagebox
import pickle
import os.path
import sys
def saving():
messagebox.showinfo("Setting Up", "Setup will now begin")
path = os.path.expanduser(appdata)
os.chdir(path)
os.makedirs(appdir)
loc = os.path.expanduser(pref_file)
new = "0"
pickle.dump(new, open(loc, "wb"))
popup = Tk()
popup.withdraw()
appdata=os.getenv('APPDATA') #modified for my convenience
appdir=os.path.join(appdata,'MyApp')
pref_file=os.path.join(appdir,'pref.pickle')
loc = os.path.expanduser(pref_file)
if (os.path.exists(loc)):
def world():
#the functions referring to the calculator
if (i == "0"):
popup.deiconify()
popup["bg"] = "#f0f0f0"
popup.title("INSTRUCTIONS")
labelpu = Label(popup, bg="white", text='instructions on usage', justify="left").grid()
popup.resizable(width=False, height=False)
var = StringVar()
check = Checkbutton(popup, text="Don't Show Again", variable=var, onvalue="1", offvalue="0",
bg="#f0f0f0")
check.deselect()
check.grid()
lbl = Label(popup, text=var.get())
btnOK = Button(popup, text="OK", bg="#f0f0f0", justify="center", width=20,command=lambda:btnOkay()).grid()
def btnOkay():
global i
lbl = Label(popup, text=var.get())
if (var.get() == "0"):
popup.withdraw()
i = "1"
#calc.deiconify()
print('deiconified calc') #added for debugging
elif (var.get() == "1"):
info = open(loc, 'w ')
new = "1"
pickle.dump(new, open(loc, "wb"))
popup.withdraw()
#calc.deiconify()
print('deiconified calc') #added for debugging
i = "1"
world()
popup.deiconify()
elif i == "1":
#calc.deiconify() commented for debugging
print('deiconified calc')
exit() #added for debugging
i = pickle.load(open(loc, "rb"))
world()
else:
saving()
messagebox.showinfo("Setup Complete", "Setup is now complete. Please restart the program to continue.")
sys.exit()
popup.mainloop()
Примечания
- У вас не было a
mainloop()
для вашей программы, из-за чего ваше окно никогда бы не появилось. - В условии не было первоначального вызова
world()
функцииif
. - Не вызывайте
world()
изelif i == "1":
условия, это приведет к бесконечной рекурсии.
Мне все еще не совсем ясно, чего именно вы хотели добиться, дайте мне знать, соответствует ли мой код вашим требованиям. Надеюсь, это помогло.
Комментарии:
1. Код был немного изменен при копировании и вставке, поскольку я делал это по частям, поэтому вышеприведенное не будет функционировать должным образом, я включил его для строк. Однако проблема возникла из-за отсутствия the
mainloop()
, которое я упустил из виду, увидев, что код выполняется правильно на python. Теперь яexe
полностью функционирую, спасибо за вашу помощь!