I'm trying to compile a Tkinter app as an executable for MacOs. I tried to use py2app
and pyinstaller
. I almost succeed using py2app
, but it returns the following error:
Traceback
The Info.plist file must have a PyRuntimeLocations array containing string values for preferred Python runtime locations.
These strings should be "otool -L" style mach ids; "@executable_stub" and "~" prefixes will be translated accordingly.
This is how the setup.py
looks like:
from setuptools import setup
APP = ['main.py']
DATA_FILES = ['config.json']
OPTIONS = {
'argv_emulation': True
}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
And this is the directory structure:
-modules/---__init.py__
| |
| -- gui_module.py
| |
| -- scraper_module.py
| |
| -- app.ico
|
-config.json
|
-countries_list.txt
|
-main.py
|
-requirements.txt
|
-setup.py
I'm happy to share more details and the files if you need them.
The problem was that you need to give an executable path for the python framework you have on your MacOs. So I modify the setup.py
from setuptools import setup
class CONFIG:
VERSION = 'v1.0.1'
platform = 'darwin-x86_64'
executable_stub = '/opt/homebrew/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib' # this is important, check where is your Python framework and get the `dylib`
APP_NAME = f'your_app_{VERSION}_{platform}'
APP = ['main.py']
DATA_FILES = [
'config.json',
'countries_list.txt',
('modules', ['modules/app.ico']),
# this modules are automatically added if you use __init__.py in your folder
# ('modules', ['modules/scraper_module.py']),
# ('modules', ['modules/gui_module.py']),
]
OPTIONS = {
'argv_emulation': False,
'iconfile': 'modules/app.ico',
'plist': {
'CFBundleName': APP_NAME,
'CFBundleDisplayName': APP_NAME,
'CFBundleGetInfoString': APP_NAME,
'CFBundleVersion': VERSION,
'CFBundleShortVersionString': VERSION,
'PyRuntimeLocations': [
executable_stub,
# also the executable can look like this:
#'@executable_path/../Frameworks/libpython3.4m.dylib',
]
}
}
def main():
setup(
name=CONFIG.APP_NAME,
app=CONFIG.APP,
data_files=CONFIG.DATA_FILES,
options={'py2app': CONFIG.OPTIONS},
setup_requires=['py2app'],
maintainer='foo bar',
author_email='foo@domain.com',
)
if __name__ == '__main__':
main()
Then you need to run python3 setup.py py2app
and now you can go and just double click on your_app_{VERSION}_{platform}.app
.
py2app
docs:--argv-emulation
when the program uses a GUI toolkit (as Tkinter) py2app options docs