Приложение TKinter отлично работает в Visual Studio Code, но вылетает как .exe

У меня есть приложение 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: Неважно, это не решило проблему. Проблема как-то связана с созданием весов. Я действительно не знаю, что делать.

Если вы используете какие-либо внешние файлы в своем приложении, убедитесь, что они находятся в том же каталоге, что и .exe, и если вы хотите также связать файлы данных в своем exe, вы можете использовать флаг --add-data и изменить свой код, как указано в stackoverflow.com/a/13790741/14094985 поскольку Pyinstaller во время выполнения распаковывает все зависимости во временный каталог.

astqx 14.12.2020 12:00

Спасибо за Ваш ответ! Единственные файлы, которые я использую, это файлы .py и файл .ico, файл .ico находится в том же каталоге, так что это не должно быть проблемой. Кроме того, я использовал try/except при каждом доступе к файлам.

Luca Tatas 14.12.2020 12:29

Хорошо, вы можете использовать флаг -c вместо флага -w, тогда результирующий исполняемый файл будет в консольном режиме, это поможет вам увидеть точные ошибки, которые происходят до сбоя вашего приложения.

astqx 14.12.2020 12:47

pyinstaller -y -F "onefile.py" - добавляет консоль, и ошибки должны появляться на этом

user11874651 14.12.2020 18:09

Я редактировал свой вопрос несколько раз, может быть, вы можете взглянуть.

Luca Tatas 14.12.2020 18:45
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
350
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ознакомьтесь с Ведение журнала и учебником, который прилагается. После форматирования для записи в файл вы можете поставить несколько 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, и все четыре шкалы правильно отображаются на моем экране, поэтому проблема не в этих конкретных строках кода, а в том, как они взаимодействуют с остальной частью вашего кода.

Я могу попытаться найти корень вашей проблемы, но мне нужно увидеть ваш полный код или минимальный воспроизводимый пример, который успешно имитирует ту же проблему, что и у вас.

Спасибо за Ваш ответ. На самом деле я сам написал функцию ведения журнала, потому что не знал, что она существует. Я отредактировал свой вопрос, чтобы вы могли видеть, с чем я работаю.

Luca Tatas 14.12.2020 18:01

Я редактировал свой вопрос несколько раз, может быть, вы можете взглянуть.

Luca Tatas 14.12.2020 18:45

Извините за поздний ответ, я лег спать сразу после того, как немного побродил по этому сайту. В любом случае, я обновил свой ответ, надеюсь, это поможет.

Andrew Stone 15.12.2020 03:29

Спасибо за ваши огромные усилия! Я заставил его работать очень хорошо, используя ttk.scales. Но у меня есть вопрос в целом: рекомендуется ли делать .mainloop() внутри класса, который вы используете в качестве графического интерфейса? Я вижу, что вы делаете .mainloop() не в инициализации, но это то, что я делаю. Есть ли разница?

Luca Tatas 15.12.2020 11:04

Пожалуйста! Рад слышать, что вы нашли решение, и вау, это довольно аккуратно, я даже не подумал попробовать поместить .mainloop() в раздел __init__. Примеры, которые я видел, помещали .mainloop() вне класса, поэтому я поместил туда свой. Я предполагаю, что у вас самая последняя строка раздела __init__, и в этом случае да, это работает так же хорошо, потому что вы вызываете все свои функции и настраиваете свой графический интерфейс перед вызовом .mainloop(), и это все, что действительно имеет значение.

Andrew Stone 15.12.2020 11:30

Да, это именно то, что я делаю! :)

Luca Tatas 15.12.2020 12:06

Другие вопросы по теме