У меня есть приложение TKinter, которое я собрал в коде Visual Studio. Он отлично работает в Visual Studio Code и не зависает или что-то в этом роде. Поскольку я хочу, чтобы моя программа работала и на других компьютерах, я создал файл .exe с помощью pyinstaller, запустив
pyinstaller --onefile -w "main.py"
Это создает нужный файл .exe без каких-либо проблем. К сожалению, когда я помещаю ее в файл .exe, моя программа часто дает сбой, под сбоем я имею в виду, что окно больше не отвечает или что окно просто закрывается через некоторое время. Я не знаю, является ли это общей проблемой, но я, честно говоря, не знаю, что делать. По-видимому, у меня нет проблем с моим кодом, потому что он отлично работает в Visual Studio Code.
Могу ли я что-нибудь сделать?
Редактировать 1: Мое окно зависает вокруг этих строк моего кода: Я пытаюсь создать 4 шкалы с циклом for:
for i in range(4):
scale = tk.Scale(self.root, state = "disabled", from_ = 100, to = 0)
scale.place(rely=0.2,relx=i*0.25,relwidth=0.25, relheight=0.8)
self.scales.append(scale)
Также я стараюсь заносить свои весы в список self.scales
, чтобы потом поработать с ними. Программа создает первые три шкалы без проблем, но часто не может создать четвертую.
Обновлено еще раз: Я думаю, что нашел решение: возможно, цикл for слишком быстр для Tkinter, и он не может так быстро создавать элементы графического интерфейса, добавил я.
time.sleep(0.1)
для моего цикла for, на данный момент это, кажется, работает. Но я действительно не знаю, так ли это должно быть.
РЕДАКТИРОВАТЬ 3: Неважно, это не решило проблему. Проблема как-то связана с созданием весов. Я действительно не знаю, что делать.
Спасибо за Ваш ответ! Единственные файлы, которые я использую, это файлы .py и файл .ico, файл .ico находится в том же каталоге, так что это не должно быть проблемой. Кроме того, я использовал try/except при каждом доступе к файлам.
Хорошо, вы можете использовать флаг -c
вместо флага -w
, тогда результирующий исполняемый файл будет в консольном режиме, это поможет вам увидеть точные ошибки, которые происходят до сбоя вашего приложения.
pyinstaller -y -F "onefile.py" - добавляет консоль, и ошибки должны появляться на этом
Я редактировал свой вопрос несколько раз, может быть, вы можете взглянуть.
Ознакомьтесь с Ведение журнала и учебником, который прилагается. После форматирования для записи в файл вы можете поставить несколько logging.info()
здесь и там, которые могут помочь определить основную причину вашей ошибки.
import logging
logging.basicConfig(filename='log.txt',
filemode='a',
format='%(asctime)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=logging.INFO)
def my_func(x, y):
logging.info('Accessing Function: my_func()')
z = x + y
logging.info(f'Function myfunc() Successfully Completed, Variable Values: {x}, {y}, {z}')
my_func(2, 7)
Теперь у вас есть удобный log.txt
файл, который вы можете диагностировать.
РЕДАКТИРОВАТЬ
Используя предоставленные вами строки кода, я попробовал следующее:
import tkinter as tk
class Application(tk.Frame):
def __init__(self, root=None):
super().__init__(root)
self.root = root
self.root.geometry('720x450')
self.pack()
self.scales = []
self.create_scale()
def create_scale(self):
for i in range(4):
scale = tk.Scale(self.root, state = "disabled", from_=100, to=0)
scale.place(rely=0.2, relx=i*0.25, relwidth=0.25, relheight=0.8)
self.scales.append(scale)
gui = tk.Tk()
app = Application(root=gui)
app.mainloop()
Я сделал exe-файл с PyInstaller 4.1, Python 3.9, и все четыре шкалы правильно отображаются на моем экране, поэтому проблема не в этих конкретных строках кода, а в том, как они взаимодействуют с остальной частью вашего кода.
Я могу попытаться найти корень вашей проблемы, но мне нужно увидеть ваш полный код или минимальный воспроизводимый пример, который успешно имитирует ту же проблему, что и у вас.
Спасибо за Ваш ответ. На самом деле я сам написал функцию ведения журнала, потому что не знал, что она существует. Я отредактировал свой вопрос, чтобы вы могли видеть, с чем я работаю.
Я редактировал свой вопрос несколько раз, может быть, вы можете взглянуть.
Извините за поздний ответ, я лег спать сразу после того, как немного побродил по этому сайту. В любом случае, я обновил свой ответ, надеюсь, это поможет.
Спасибо за ваши огромные усилия! Я заставил его работать очень хорошо, используя ttk.scales. Но у меня есть вопрос в целом: рекомендуется ли делать .mainloop() внутри класса, который вы используете в качестве графического интерфейса? Я вижу, что вы делаете .mainloop() не в инициализации, но это то, что я делаю. Есть ли разница?
Пожалуйста! Рад слышать, что вы нашли решение, и вау, это довольно аккуратно, я даже не подумал попробовать поместить .mainloop()
в раздел __init__
. Примеры, которые я видел, помещали .mainloop()
вне класса, поэтому я поместил туда свой. Я предполагаю, что у вас самая последняя строка раздела __init__
, и в этом случае да, это работает так же хорошо, потому что вы вызываете все свои функции и настраиваете свой графический интерфейс перед вызовом .mainloop()
, и это все, что действительно имеет значение.
Да, это именно то, что я делаю! :)
Если вы используете какие-либо внешние файлы в своем приложении, убедитесь, что они находятся в том же каталоге, что и
.exe
, и если вы хотите также связать файлы данных в своем exe, вы можете использовать флаг--add-data
и изменить свой код, как указано в stackoverflow.com/a/13790741/14094985 поскольку Pyinstaller во время выполнения распаковывает все зависимости во временный каталог.