Update: This entry has been updated for Snow Leopard.
In all of Mac-dom, there are few experiences more painful than trying to get Python tools to talk to a MySQL database. Installing MySQL itself is easy enough – Sun provides a binary package installer. Python 2.5 comes with Mac OS X. If you enable Apache and PHP, your PHP scripts will talk to your installed MySQL databases just fine, since PHP comes bundled with a MySQL database connector. But try to get up and running with Django, TurboGears, or any other Python package where MySQL database access could be useful (or needed), and you’re in for a world of hurt.
Update: I finally did manage to get Python and MySQL playing nice together, but it took a few more contortions beyond what’s described in the recipes found scattered around the interwebs. I’ve added my solution at the end of this post.
First, the official mysql-python package available at SourceForge does not offer a .pkg installer. No problem – we can build from source. Ah, but the source code is developed for and tested on Linux, and has apparently never been test-built on Mac OS X by the maintainers. The usual
python setup.py buildsudo python setup.py install
will not work. Search for “mac python mysql binding” and you’ll find dozens (hundreds?) of sites describing processes you can go through to edit a few of the source files so they’ll compile on OS X. Some of them work, some of them don’t. I spent three hours yesterday trying one recipe after another. I tried mysql-python versions 1.2.1, 1.2.2, and the beta version of 1.2.3. The recipes that would get python-mysql to build and install still failed when I attempted
import MySQLdb from within Python. Complaints of the same problem largely go unanswered – presumably people just give up.
easy_install is no help either – it chokes because it can’t find the path to
mysql_config, and there’s no way to hand it one (that I can tell.)
Judging by timestamps on old blog entries, this sorry state of affairs has been going on for years. Developers wasting hours trying to get a simple db connector to compile… but it never seems to get fixed. “It’s open source,” you say – “Fix it and contribute your fixes back to the community.” I would. I’d love to. But I can’t get the damn thing to compile and install cleanly, despite all the recipes out there. Even seasoned developers in #django offer responses like “Yeah, I remember that was a huge PITA. I eventually got it to compile, but don’t remember how.”
There is another option – a precompiled python-mysql connector does exist, but only available through the MacPorts project, which aims to remove some of the pain of installing common *nix tools on OS X. But there’s a rub – the connector available through MacPorts only ships with the complete MacPorts version of MySQL. So unless you want to avoid the confusion of having two RDBMs running at the same time, you’ll need to rip the official MySQL (and its startup item) out of your system before you begin. Of course, if you’ve already got data stored in those databases, you’ll need to back up that data first. Even then, getting the MacPorts version of MySQL up and running is no picnic either. You’re still going to end up with a lot of post-install configuration, tweaking, permissions issues, etc. This shouldn’t be necessary. There should be an installer that works with Sun’s stock MySQL dist and Apple’s bundled python. You shouldn’t need to alter your whole system config for this one little piece.
You have to wonder how many people have gotten curious about Python development, hit their heads on this brick wall, and thrown up their hands. As Keenan Thomson would say, “FIX IT!!!”
Someone out there knows how to create a mysql-python package that’s as easy to install as MySQL itself. We need to identify that person, offer them some bread for their trouble, and get this problem fixed for once and for all.
Note: I am no longer running a tipjar to get this work done. For whatever reason, we’re not seeing many contributions, and I’ve got the problem solved now (painful as it was). If you’d like to take up the mantle, go for it.
On the other hand, if you’re a web developer who’s tired of banging your head against this ridiculous wall, please leave a few bucks for the developer who promises to solve the problem for once and for all. When deciding how much to commit, consider your regularly hourly rate, then estimate how many hours you’ve spent trying to get over this hurdle. In other words, I’m guessing that having this fixed is probably worth more to you than $5… but whatever you can contribute is appreciated. I’ll manage the collection and pledge to turn the whole sum over to the first developer who can package up a py25-mysql database connector that “just works” with Sun’s stock MySQL for OS X and Apple’s python 2.5. Users should not need to download 1GB of XCode just to get a compiler or jump through any other hoops. Just a simple installer (CLI OK, but .pkg preferred).
OK, so I finally did solve this one. I’ve actually been trying to configure two machines at once, and running into different problem sets — the usual recipes (this is my favorite, but do step #6 before step #0) did work for one machine, but not for the other. One one machine, I thought it wasn’t working because of error messages returned when trying to
import MySQLdb from a Python shell. Turns out you can ignore some of these errors and things will still work from within a Python app.
On the other machine, the problem went deeper. I got errors when trying to
import MySQLdb, but they were different :
Error loading MySQLdb module: dynamic module does not define init function (init_mysql)
I’m not sure what was different about the two machines, but it was a showstopper. Here’s how I finally solved it.
First of all, don’t use any of the instruction sets you’ll find online for building/installing the mysql-python binding. If you’re getting the “does not define init function” error, the usual recipes won’t work for you (no, I don’t know why – they just won’t).
1) Download, install, and configure the MySQL server dmg from Sun, along with the StartupItem and PreferencePane. Get MySQL itself up and running, with root permission established, etc.
2) Install MacPorts, then use it to retrieve the whole python-mysql package:
/opt/local/bin/port install py25-mysql
This will take a while – it unfortunately is going to compile/install a complete mysql server, along with the bindings you need. However, it won’t set it to launch on boot or anything, so it won’t mess with anything on your system.
3) All we need are the properly compiled bindings from the py25-mysql package, which we’ll copy to the system’s site-packages dir. So:
$ cd /opt/local/lib/python2.5/site-packages # Copy two dirs and three files to system's site-packages dir sudo cp -r MySQL_python-1.2.2-py2.5.egg-info /Library/Python/2.5/site-packages sudo cp -r MySQLdb /Library/Python/2.5/site-packages sudo cp -r _mysql* /Library/Python/2.5/site-packages
4) You can now start a Python shell and enter
import MySQLdb with no errors. Yay! But… you still won’t be able to connect to your server from a configured Django project — it’ll complain about not being to find a mysql socket file at
/opt/local/var/run/mysql5/mysqld.sock. Not sure what causes that, but it’s easy to fix. In the
settings.py for your Django project, specify a path to the socket file as the DATABASE_HOST:
DATABASE_HOST = '/tmp/mysql.sock'
You’re in business.
Good news: Snow Leopard upgrades Python to 2.6.1. Bad news: It’ll break your MySQL installation as well as your Python-MySQL database connector. Fortunately, getting things working is a bit easier than it was under Leopard, and you won’t need to rely on MacPorts at all..
I had an older 32 bit version of MySQL installed. With a bit of futzing I was able to get my old MySQL installation running again, but could not get the python-mysql binding working. Finally installed the latest 64-bit version from mysql.com. Before installing, be sure to export the databases you want to keep first! My databases were blown away by the upgrade, and I had to restore them. Get your databases reinstalled, privileges established, and make sure you can connect to your mysql server normally.
To reinstall the Python MySQL connector you’ll need the gcc compiler, which you’ll also find has been blown away in the Snow Leopard upgrade. To get gcc reinstalled, run the Xcode installer from the Snow Leopard DVD.
Now grab the latest version of the python-mysql connector (check to make sure that’s the most current download URL when you read this).
Unpack the archive and cd into its directory. Here’s the key: You’ll need to specify your 64-bit architecture during the compile process:
ARCHFLAGS='-arch x86_64' python setup.py build ARCHFLAGS='-arch x86_64' python setup.py install
If you get the error “mysql_config not found” follow the instructions here, which are essentially this: Open up site.cfg from the binding distribution and make sure it has this (the path to mysql_config should match the actual one on your system):
mysql_config = /usr/local/mysql/bin/mysql_config
Save the file, try the build again, and it should work.
You should now be able to launch a Python shell and type:
>>> import MySQLdb
and get no errors. And your Django projects should work just fine. If you get an error that the shared library (the binding .so) couldn’t be found, you probably need to export the DYLIB path. Try this in a shell before starting Python:
Then try importing MySQLdb again. If it works, add that line to your .profile.