0

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!

Nathan Wolf
  • 336
  • 3
  • 12
  • It could also be an issue with different versions of macOS, but why does it run fine as an executable but not an app? – Nathan Wolf Feb 27 '22 at 00:20
  • You might be running into a permissions error due to [Transparency, Consent, and Control (TCC)](https://apple.stackexchange.com/questions/332673/what-and-how-does-macos-mojave-implement-to-restrict-applications-access-to-pers) system, which requires user authorization for an app to access any private data... and recent versions consider the Downloads folder to be private. Under Terminal, it may work because it inherit's whatever authorizations you've given the Terminal app. I'd recommend keeping any data files in a non-TTC-controlled location. – Gordon Davisson Feb 27 '22 at 02:58
  • Also, `/Users/{userName}/` is not necessarily where a user's home folder is located. See [this question](https://stackoverflow.com/questions/4028904/what-is-the-correct-cross-platform-way-to-get-the-home-directory-in-python) for some better methods to locate it. – Gordon Davisson Feb 27 '22 at 03:01
  • {userName} looks like input formatting for preprocessing... to get the home directory, use the os module. https://stackoverflow.com/questions/842059/is-there-a-portable-way-to-get-the-current-username-in-python – Richard Barber Feb 27 '22 at 06:43

0 Answers0