Distributing a python application to MacOS X
Today I needed to create an app file for MacOS X with a simple Python script. This is what I learned:
- Use py2app, it's your friend
- After installing py2app with easy_install you need to fix it. Otherwise it may not work for your hardware architecture. See Section 2 of this blog post
- Now, you can safely run python setup.py py2app and you will get a file with the .app extension in the dist directory
- When you install that (copy into your Applications folder) and try to run it you will get this error (open the Console or do a tail -f /var/log/system.log) to see the error:
22/03/11 10:33:21 com.apple.launchd.peruser.502[580] ([0x0-0x98098].org.pythonmac.unspecified.myscript1613]) Exited with exit code: 255
22/03/11 10:34:53 [0x0-0x9b09b].org.pythonmac.unspecified.myscript[1645] Traceback (most recent call last):
22/03/11 10:34:53 [0x0-0x9b09b].org.pythonmac.unspecified.myscript[1645] File "/Applications/xml2rfc.app/Contents/Resources/__boot__.py", line 103, in <module>
22/03/11 10:34:53 [0x0-0x9b09b].org.pythonmac.unspecified.myscript[1645] _argv_emulation()
22/03/11 10:34:53 [0x0-0x9b09b].org.pythonmac.unspecified.myscript[1645] File "/Applications/xml2rfc.app/Contents/Resources/__boot__.py", line 101, in _argv_emulation
22/03/11 10:34:53 [0x0-0x9b09b].org.pythonmac.unspecified.myscript[1645] _get_argvemulator().mainloop()
22/03/11 10:34:53 [0x0-0x9b09b].org.pythonmac.unspecified.myscript[1645] File "/Applications/xml2rfc.app/Contents/Resources/__boot__.py", line 40, in mainloop
22/03/11 10:34:53 [0x0-0x9b09b].org.pythonmac.unspecified.myscript[1645] stoptime = Evt.TickCount() + timeout
22/03/11 10:34:53 [0x0-0x9b09b].org.pythonmac.unspecified.myscript[1645] AttributeError: 'module' object has no attribute 'TickCount'
In order to avoid it you need to use a different Python from your system Python. In my case it only worked with a 32 bits Python like python-2.7.1-macosx10.3.dmg
Once you have the script installed you can run it from the shell in /Applications/myscript/MacOS/myscript.py
For the record, this is my setup.py file:
import sys
from setuptools import setup
extra_options = dict(
setup_requires=['py2app'],
app=[mainscript],
# Cross-platform applications generally expect sys.argv to
# be used for opening files.
options=dict(py2app=dict(argv_emulation=True)),
)
elif sys.platform == 'win32':
extra_options = dict(
setup_requires=['py2exe'],
app=[mainscript],
)
else:
extra_options = dict(
# Normally unix-like platforms will use "setup.py install"
# and install the main script as such
scripts=[mainscript],
)setup(
name='myscript',
version='0.1.0',
**extra_options
)
It's taken from a py2app example