【问题标题】:TKinter application runs perfectly fine in Visual Studio Code but crashes as an .exeTKinter 应用程序在 Visual Studio Code 中运行良好,但作为 .exe 崩溃
【发布时间】:2021-03-24 22:59:37
【问题描述】:

我有一个 TKinter 应用程序,我将它放在 Visual Studio Code 中。它在 Visual Studio Code 中运行得非常好,并且不会冻结或类似的东西。因为我希望我的程序也可以在其他电脑上运行,所以我使用 pyinstaller 通过运行创建了一个 .exe 文件

pyinstaller --onefile -w "main.py"

这会毫无问题地创建所需的 .exe 文件。可悲的是,当放入 .exe 文件时,我的程序经常崩溃,崩溃是指窗口不再响应,或者窗口在一段时间后自行关闭。 我不知道这是否是一个常见问题,但老实说,我不知道该怎么办。 显然我的代码没有任何问题,因为它在 Visual Studio Code 中运行得非常好。

有什么我可以做的吗?

编辑 1: 我的窗口在我的代码的这些行周围冻结: 我正在尝试使用 for 循环创建 4 个比例:

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,以便以后可以使用我的体重秤。该程序可以毫无问题地创建前三个音阶,但通常无法创建第四个音阶。

编辑 2: 我想我找到了一个解决方案:也许 for 循环对于 Tkinter 来说太快了,它无法快速创建 GUI 项目,我补充道

time.sleep(0.1)

对于我的 for 循环,目前,这似乎可行。但我真的不知道它是否应该是这样的。

编辑 3: 没关系,这并没有解决问题。这个问题与创建音阶有关。 我真的不知道该怎么办。

【问题讨论】:

  • 如果您在应用程序中使用任何外部文件,请确保它们与.exe 位于同一目录中,并且如果您也希望将数据文件捆绑在您的 exe 中,您可以使用标记--add-data 并按照stackoverflow.com/a/13790741/14094985 中的说明修改您的代码,因为Pyinstaller 在执行期间将所有依赖项解压缩到一个临时目录。
  • 感谢您的回答!我使用的唯一文件是 .py 文件和 .ico 文件,.ico 文件位于同一目录中,所以这应该不是问题。除此之外,我在访问文件时都使用了 try/except。
  • 好的,您可以使用-c 标志而不是-w 标志,这样生成的可执行文件将处于控制台模式,这将帮助您查看您之前发生的确切错误应用程序崩溃。
  • pyinstaller -y -F "onefile.py" - 添加一个控制台,错误应该在此提示
  • 我的问题编辑了多次,也许你可以看看。

标签: python windows tkinter pyinstaller exe


【解决方案1】:

查看Logging,以及随附的tutorial。格式化写入文件后,您可以在这里和那里放几个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()

我使用 PyInstaller 4.1、Python 3.9 制作了一个 exe,并且所有四个比例都在我的屏幕上正确生成,所以问题不在于这些特定的代码行,而是它们如何与您的其余代码交互。

我可以尝试找出您问题的根源,但我需要查看您的完整代码或成功模仿您遇到的相同问题的minimal, reproducible example

【讨论】:

  • 感谢您的回答。实际上,我自己编写了一个日志记录功能,因为我不知道它存在。我编辑了我的问题,所以你可以看到我正在处理什么
  • 我的问题我编辑了很多次,也许你可以看看。
  • 抱歉回复晚了,我在这个网站上浏览了一会儿就上床睡觉了。无论如何,我更新了我的答案,希望对您有所帮助。
  • 感谢您的巨大努力!我通过使用 ttk.scales 让它工作得很好。但我一般有一个问题:是否建议在您用作 GUI 的类外部执行 .mainloop() ?我看到您不是在 init 中执行 .mainloop(),但这就是我正在执行的操作。有什么区别吗?
  • 不客气!很高兴听到您找到了解决方案,哇,这真是太棒了,我什至没有想过尝试将 .mainloop() 放在 __init__ 部分中。我看到的例子把.mainloop() 放在课堂之外,所以这就是我把我的例子放在那里的原因。我假设您的代码是__init__ 部分的最后一行,在这种情况下,是的,它完全可以正常工作,因为您在调用.mainloop() 之前调用了所有函数并设置了您的gui,这才是真正重要的.
猜你喜欢
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-01
  • 2023-04-07
  • 1970-01-01
相关资源
最近更新 更多