Fail to build a standalone executable file on MacOS

743 Views Asked by At

I want to make a standalone executable out of a script on a MacOS (10.14).

The script is my_app.py and has the following content:

#!/usr/bin/env python

import os.path
import csv
import pandas as pd

##1 open the file
f=open("path/to/original_file.txt", "r")

filedata = f.read()
##1

##1.1 replace the desired characters
filedata = filedata.replace("\\", ",")
filedata = filedata.replace("*", "")

with open("path/to/new_file.txt", 'w') as file:
  file.write(filedata)
##1.1

and the following setup.py file:

from setuptools import setup

APP = ["my_app.py"]
DATA_FILES = []
OPTIONS = {
    "argv_emulation": True,
    "packages": ["certifi"],
}
setup(
    app = APP,
    data_files = DATA_FILES,
    options = {"py2app": OPTIONS},
    setup_requires = ["py2app"]

)

Following the steps in a previous SO questions with answer, I entered sequentially the following commmands in Terminal:

pip install virtualenv
virtualenv venv --system-site-packages
source venv/bin/activate
pip3.7 install -U py2app
cd /path/to/my_app.py
python setup.py py2app -A

However when I double click on my_app.app (which have just been created and which is located in /Users/mymac/Documents/applications/myapp/dist) I get the following error message in a pop-up window

enter image description here

What am I doing wrong? Does it have to do with the fact that there is no GUI framework in my app (like PyQT or Tkinter)?

2

There are 2 best solutions below

4
On

Mist likely you need to include a runtime library of some sort but another option is to create a script to run your app and then fix so that you can start your script from the Finder by double clicking it, see this question for some alternative ways to do it.

The easiest way mentioned in the linked question is to give the script the extension .command then you shouldn’t need to do anything else.

The advantage of using a script is that it’s executed in the Terminal (in a shell) so you should have all the libraries etc available automatically.

0
On

I could finally build a standalone by

  • wrapping the application around a PyQt framework
  • use PyInstaller to build the app

The my_app.py should look like this:

import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QSize

class HelloWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.setMinimumSize(QSize(640, 480))
        self.setWindowTitle("Hello world")

        centralWidget = QWidget(self)
        self.setCentralWidget(centralWidget)

        gridLayout = QGridLayout(self)
        centralWidget.setLayout(gridLayout)

        title = QLabel("Hello World from PyQt", self)
        title.setAlignment(QtCore.Qt.AlignCenter)
        gridLayout.addWidget(title, 0, 0)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = HelloWindow()
    mainWin.show()
    sys.exit( app.exec_() )

Then you cd the directory where the my_app.py resides. You then then run

PyInstaller my_app.py

This will create several directories: __pycache__, build and dist. Inside the dist there is another directory named my_app. In this directory there will be an executable named my_app (or referring to the original question, inside the path path/to/dist/my_app/) ==> double click on it and your app is running!