Jul 27 2008
As I’ve posted, I’ve recently begun to ‘breed snakes’, meaning that I’m learning Python when I’m in the mood for some private hacking.
My Python and wxPython installations are the default ones that come pre-installed on OS X Leopard. So far, I’ve been avoiding a customized installation.
I’m using the Eclipse/PyDev combo for my editing, and I really, really begin to like it. No offense to anybody else, but Eclipse is one of the three great Java desktop applications that I’ve seen. (The other two are ‘Tribal Trouble’ and ‘Cyberduck’). Eclipse performs very well, and I just like using it. It’s a personal preference – just use whatever you like and prefer and be happy with it. I’m not religious about that stuff. But I also openly say that I’ve yet to see other good Java desktop applications; most of the Java desktop stuff that I’ve come across looks either out of place or is slow or just plainly sucks. But this posting is not about Java.
Coming back to Python. Today, I’ve been toying a bit with wxPython and I wanted to see how easy – or difficult – it is to create a Macintosh application bundle of a wxPython application with py2app.
So I have this mini wxPython source code here that does not much except for drawing an application window – pardon: frame – and showing a Mac-style menu:
import wx class App(wx.App): def OnInit(self): frame=wx.Frame(parent=None, title='MyTitle') frame.menu_bar = wx.MenuBar() frame.help_menu = wx.Menu() frame.help_menu.Append(wx.ID_ABOUT, "&About MyTitle") frame.menu_bar.Append(frame.help_menu, "&Help") frame.SetMenuBar(frame.menu_bar) frame.Bind(wx.EVT_MENU, self.on_about_request, id=wx.ID_ABOUT) frame.Show() self.SetTopWindow(frame) return True def MacOpenFile(self, filename): print filename def on_about_request(self,event): print "About." app=App() app.MainLoop()
The few lines of Python code above are stored in a file named NNTP.py in my Eclipse project, and the following code is stored in setup.py in the very same project:
from distutils.core import setup import py2app setup( app=['NNTP.py'] )
This should be run like so:
python setup.py py2app
Or, to make your life even simpler, right click on “setup.py” in the Eclipse Navigator, select “Properties”, then “Edit” the “Run/Debug settings” of setup.py, click on “(x)= Arguments” and add “py2app” to the “Program arguments”. “Apply”/”OK” everything. When you now run the script within Eclipse, you won’t see any error messages, but it will actually create the Macintosh application bundle for you. You will find it in the “dist” folder within your project’s structure in the directory that holds your Eclipse workspace.
The good news is that py2app generates a Universal Binary for you, and in my case it runs both on my PowerPC notebook and my Intel Mac Pro.
The bad news are that it is more than 23 Megabytes in size and it does not run on OS X Tiger. The latter does not make me very happy: It makes the deployment of Python application bundles messy at best.
I have also seen this problem before. The Python game Solarwolf, for example, does not run on OS X Leopard; it was built for OS X Tiger (PowerPC) and that is the only version of Mac OS X on which it runs.
This is bad and in my opinion, deployment nightmares like this should have been fixed years ago – on any system and for any development platform. BlitzMax, the so-called game programming language, does a much better job here than Python. Sure, you won’t get a Universal Binary out of the box in BlitzMax (you actually have to compile your app on both an Intel and a PowerPC machine and then have to do some hand work), but at least the application bundle will not only run on one specific version of Mac OS X.
Deploying Python applications is not yet an issue for me, so I’ve got plenty of time to look into this more thoroughly. There probably is a solution, and maybe even a simple one. But I have a mixed first impression nevertheless. On one side, I am quite happy that so far creating an application bundle is relatively simple. On the other side, I am disappointed that a created bundle only seems to work on the OS X version on which it was built.
Well, let’s see what more I will find out when I dive deeper into this.
The answer is not to use the Python/wxPython/py2app versions that come with Leopard, but the ‘official’ distributions from Python.org and wxPython.org:
1. Download MacPython 2.5.2 from http://www.python.org/ftp/python/2.5.2/python-2.5.2-macosx.dmg and install it.
2. Download wxPython from http://downloads.sourceforge.net/wxpython/wxPython2.8-osx-unicode-18.104.22.168-universal-py2.5.dmg and install it.
3. Download the source tarball version of py2app from http://pypi.python.org/pypi/py2app/0.3.6 and ‘sudo python setup.py’-install it.
4. I also made sure that in Eclipse’s preferences in the PyDev section, the Python interpreter ‘python2.5′ in /Library/Frameworks/Python.framework/Versions/2.5/Resources/Python.app/Contents/MacOS/Python is used.
(Note: I intentionally did not use hyperlinks here.)
After that, the bundles created on Leopard also run on Tiger.