Apple 应用程序与 unix 可执行文件和 .app 文件的运行方式不同

发布于 2025-01-10 06:17:51 字数 3203 浏览 0 评论 0原文

我正在尝试制作一个独立的 Mac 应用程序,一旦人们拥有应用程序文件,该应用程序将在我以外的计算机上运行。从结构上来说,它非常简单。一个 python 文件包含所有 tkinter 相关内容,另一个文件处理逻辑。还有一个 python 文件从中读取的 json 文件。我使用 pyinstaller 捆绑所有内容并获得了一个在我的计算机上运行良好的 .app 文件。然而,在其他人的计算机上,他们无法访问该应用程序的某一特定页面。由于它在我的计算机上运行,​​因此错误必须来自我们计算机之间的不同之处,因此我认为它与文件路径有关。此外,他们看不到的视图是唯一涉及写入文件的视图。然后我发现了一些奇怪的事情。如果您进入应用程序的内容并在终端中运行主 unix 可执行文件(我这样做是为了获得描述错误的文本输出),则该应用程序在他们的计算机上完美正常运行。为什么这有效?是什么导致它作为 .app 文件失败但作为 unix 可执行文件运行?

这是我的代码,用于转到失败视图的按钮和失败视图

#Function called by button to load the view that failed   
 def check_answer(self, question, response):
        self.answerView = AnswerView(self.container, self, question, response)
        self.answerView.grid(row=0, column=0, sticky="nsew")
        self.answerView.tkraise()
#AnswerView class
class AnswerView(tk.Frame):
    def nextQ(self):
        global questionNum
        if questionNum == len(questions) - 1:
            self.controller.quit_game()
        else:
            questionNum += 1
            nextQ = questions[questionNum]
            self.controller.view_question(nextQ)

    def __init__(self, parent, controller, question: Question, response: str):
        global resultsList
        global correctNum
        global done
        if question is None or response is None:
            Frame.__init__(self, parent)
            self.controller = controller
            pass
        else:
            Frame.__init__(self, parent)
            self.controller = controller
            if question.type == 'multiple_choice':
                answer = question.realAnswer
            else:
                answer = question.answer
            correct = question.check_answer(response)
            resultsList += [{
                "question": question.question,
                "correctAns": answer,
                "response": response,
                "correct": correct,
                "difficulty": question.difficulty,
                "category": question.category
            }]
            userName = sys.argv[0].split('/')[2]
            with open(f'/Users/{userName}/Downloads/{userName}TriviaResults.json', 'w') as results_file:
                json.dump(resultsList, results_file, indent=0)

            done += 1
            if correct:
                feedback = Label(self, text="RIGHTO!", fg='green').pack()
                correctNum += 1
                print(f"it's right! for the {correctNum}th time!")
            else:
                feedback = Label(self, text=f'INCORRECT, YOU FOOL! The correct answer was {answer}', fg='red').pack()
            nextButton = Button(self, text="Next Question", command=self.nextQ).pack()
            quitButton = Button(self, text="End Game", command=lambda: self.controller.quit_game()).pack()
#code to deal with file paths of stuff within the app
def resource_path(path: os.PathLike):
    return os.path.join(os.path.dirname(sys.argv[0]), path)

这些是代码中对 sys 的唯一引用,我认为 sys 中的内容将在不同的计算机上会有所不同,因此这是一个可能的候选者。

我不想给您带来大量代码的负担,但如果您提出要求,我很乐意提供更多代码。我知道这里有很多可能相关的信息。 谢谢!

I am trying to make a standalone mac app that will run on computers other than mine once people have the app file. Structure-wise, it is very simple. One python file has all of the tkinter related stuff, and another handles the logic. There is also a json file that the python files read from. I used pyinstaller to bundle everything and got a .app file that ran perfectly well on my computer. However, on someone else's computer, they couldn't get to one particular page of the app. Since it worked on my computer, the error had to be coming from something that differed between our computers, so I assumed it was related to file paths. Furthermore, the view they couldn't see was the only view that involved writing to a file. Then I found out something strange. If you go into the contents of the app and run the main unix executable in terminal (which I did so I could get a text output describing the error), the app runs perfectly normally on their computer. Why does this work? What is making it fail as a .app file but work as a unix executable?

Here is my code for the button that goes to the failed view and the failed view

#Function called by button to load the view that failed   
 def check_answer(self, question, response):
        self.answerView = AnswerView(self.container, self, question, response)
        self.answerView.grid(row=0, column=0, sticky="nsew")
        self.answerView.tkraise()
#AnswerView class
class AnswerView(tk.Frame):
    def nextQ(self):
        global questionNum
        if questionNum == len(questions) - 1:
            self.controller.quit_game()
        else:
            questionNum += 1
            nextQ = questions[questionNum]
            self.controller.view_question(nextQ)

    def __init__(self, parent, controller, question: Question, response: str):
        global resultsList
        global correctNum
        global done
        if question is None or response is None:
            Frame.__init__(self, parent)
            self.controller = controller
            pass
        else:
            Frame.__init__(self, parent)
            self.controller = controller
            if question.type == 'multiple_choice':
                answer = question.realAnswer
            else:
                answer = question.answer
            correct = question.check_answer(response)
            resultsList += [{
                "question": question.question,
                "correctAns": answer,
                "response": response,
                "correct": correct,
                "difficulty": question.difficulty,
                "category": question.category
            }]
            userName = sys.argv[0].split('/')[2]
            with open(f'/Users/{userName}/Downloads/{userName}TriviaResults.json', 'w') as results_file:
                json.dump(resultsList, results_file, indent=0)

            done += 1
            if correct:
                feedback = Label(self, text="RIGHTO!", fg='green').pack()
                correctNum += 1
                print(f"it's right! for the {correctNum}th time!")
            else:
                feedback = Label(self, text=f'INCORRECT, YOU FOOL! The correct answer was {answer}', fg='red').pack()
            nextButton = Button(self, text="Next Question", command=self.nextQ).pack()
            quitButton = Button(self, text="End Game", command=lambda: self.controller.quit_game()).pack()
#code to deal with file paths of stuff within the app
def resource_path(path: os.PathLike):
    return os.path.join(os.path.dirname(sys.argv[0]), path)

Those are the only references to sys in the code, and I figured the stuff in sys would be different on different computers so that was a likely candidate.

I didn't want to burden you with a ton of code, but I am happy to provide more if you ask. I know there is a lot of info that could potentially be relevant here.
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文