So I have this nice shiny MacBook pro that I’d like to start doing my programming on.  Prior to this I was using a combination of a Linux server and a Windows laptop for development work.  All of my prior development on my (older) Mac was in Java.  My new machine is a Core 2 Duo MacBook Pro running Leopard (this become important).

Java is nice… libraries are all .jar files that are so platform independent you rarely have to worry about Mac/Linux/Windows issues (for the most part).  However, I’ve been trying to expand my programming languages by adding Python to the list.  I’ve been working with Python a decent amount recently and found it to be quite pleasant.

So when it came time to start a new set of data analysis, I thought, ehh, I’ll just do it in Python.

And that was my mistake.

I got MySQL installed pretty easily by downloading the x86_64 Mac binary from mysql.com.  This went off without a hitch.

Next I tried to install MySQL-Python.  First I tried easy_install, and that failed with:

In file included from /usr/local/mysql/include/mysql.h:47,
                from _mysql.c:40:
/usr/include/sys/types.h:92: error: duplicate ‘unsigned’
/usr/include/sys/types.h:92: error: two or more data types in declaration specifiers

error: Setup script exited with error: command ‘gcc’ failed with exit status 1

That doesn’t look good. Lo and behold, there is a bug in the python-mysql library. But wait, isn’t python platform independent? Well… kinda. As it turns out Python is the funky hybrid system where some of the libraries can be compiled C and others pure Python. From the Java perspective, it’s similar to having some JNI native code mixed in… only this particular library doesn’t do it very well (on a Mac).

But, I’m a smart guy… I used to be a C guy in a former life, and I know how to use Google.  Turns out, it’s a very simple fix.  A few commented out lines, and  a s/uint/unsigned integer/g later and I’m in business.  I run:

python setup.py build
python setup.py install 

and hope for the best… but I’d be wrong.  If you try to import MySQLdb in python, you get this error:

Traceback (most recent call last):
  File “<stdin>”, line 1, in <module>
  File “build/bdist.macosx-10.5-i386/egg/MySQLdb/__init__.py”, line 19, in <module>
  File “build/bdist.macosx-10.5-i386/egg/_mysql.py”, line 7, in <module>
  File “build/bdist.macosx-10.5-i386/egg/_mysql.py”, line 6, in __bootstrap__

ImportError: dynamic module does not define init function (init_mysql)

which means absolutely nothing to me.  Turns out, I’m not the only one.
Here’s the issue.  If you look a little closer to the gcc output when building mysql-python, you see this gem at the bottom:

gcc -fno-strict-aliasing -Wno-long-double -no-cpp-precomp -mno-fused-madd -fno-common -dynamic -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DMACOSX -I/usr/include/ffi -DENABLE_DTRACE -pipe -Dversion_info=(1,2,2,'final',0) -D__version__=1.2.2 -I/usr/local/mysql/include -I/System/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5 -c _mysql.c -o build/temp.macosx-10.5-i386-2.5/_mysql.o -Os -arch x86_64 -fno-common

gcc -Wl,-F. -bundle -undefined dynamic_lookup -arch i386 -arch ppc build/temp.macosx-10.5-i386-2.5/_mysql.o -L/usr/local/mysql/lib -lmysqlclient_r -lz -lm -o build/lib.macosx-10.5-i386-2.5/_mysql.so

ld warning: in build/temp.macosx-10.5-i386-2.5/_mysql.o, file is not of required architecture
ld warning: in /usrld warning: in build/temp.macosx-10.5-i386-/local/mysql2.5/_mysql.o,/lib/libmysqlclient_r.dylib, file is not of required architecture
file is not of required architecture
ld warning: in /usr/local/mysql/lib/libmysqlclient_r.dylib, file is not of required architecture

Did you catch that? I’ll give you a clue… check out the -arch flags. Remember, I’m running x86_64 MySQL. Bingo! the .so file is built as i386 and ppc. The .o file is correctly built as x86_64, but the next step fails. So maybe if we just add an -arch x86_64 to the second gcc command, we should be in business, right? (I removed -arch ppc and -arch i386 in both gcc lines, and re-ran them)
Right?


$ gcc -fno-strict-aliasing -Wno-long-double -no-cpp-precomp -mno-fused-madd -fno-common -dynamic -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DMACOSX -I/usr/include/ffi -DENABLE_DTRACE -pipe -Dversion_info=”(1,2,2,’final’,0)” -D__version__=1.2.2 -I/usr/local/mysql/include -I/System/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5 -c _mysql.c -o build/temp.macosx-10.5-i386-2.5/_mysql.o -Os -arch x86_64 -fno-commonin

$ gcc -Wl,-F. -bundle -undefined dynamic_lookup -arch x86_64 build/temp.macosx-10.5-i386-2.5/_mysql.o -L/usr/local/mysql/lib -lmysqlclient_r -lz -lm -o build/lib.macosx-10.5-i386-2.5/_mysql.so

$ python setup.py install

Finally, no compiler errors! No linker errors! Now to try to import MySQLdb from python again…”
and FAIL


Traceback (most recent call last):
File “”, line 1, in
File “build/bdist.macosx-10.5-i386/egg/MySQLdb/__init__.py”, line 19, in
File “build/bdist.macosx-10.5-i386/egg/_mysql.py”, line 7, in
File “build/bdist.macosx-10.5-i386/egg/_mysql.py”, line 6, in __bootstrap__
ImportError: dlopen(/Users/mbreese/.python-eggs/MySQL_python-1.2.2-py2.5-macosx-10.5-i386.egg-tmp/_mysql.so, 2): no suitable image found. Did find:
/Users/mbreese/.python-eggs/MySQL_python-1.2.2-py2.5-macosx-10.5-i386.egg-tmp/_mysql.so: mach-o, but wrong architecture

What on earth am I doing wrong? I removed the i386 from the .egg file, and checked that too. Still no joy. If I look at that file, I see that it is x86_64


$ file /Users/mbreese/.python-eggs/MySQL_python-1.2.2-py2.5-macosx-10.5.egg-tmp/_mysql.so
/Users/mbreese/.python-eggs/MySQL_python-1.2.2-py2.5-macosx-10.5.egg-tmp/_mysql.so: Mach-O 64-bit bundle x86_64

Hmm… what about python itself? Now, this is stock Python 2.5 from Apple.


$ file `which python`
/usr/bin/python: Mach-O universal binary with 2 architectures
/usr/bin/python (for architecture ppc7400): Mach-O executable ppc
/usr/bin/python (for architecture i386): Mach-O executable i386

My current theory is that since Python is 32-bit only it can only link to 32 bit only libraries (makes sense). However, MySQL is installed as 64-bit only and only has 64 bit libraries (also makes sense). So never the two shall mix… it’s like oil and water. 

I’m going to try to see if a 32-bit install of MySQL will work, but that pretty much seems like a shame to have to roll back to 32 bit MySQL just to satisfy Python. Perhaps it would have been easier to just stick to Java.


  1. D

    You are right. Don’t mix 32 and 64. I have had the same issue. 32 bit MySQL works fine. It was easier for me to get 32 bit MySQL than build 64 bit Python :-)

  2. Paul Solt

    I came across your post, have you looked at this link? http://groups.google.com/group/comp.lang.python/browse_thread/thread/7bef767753fe40f1/e97805aeee35ec0b

    geert mentions stuff about 64 bit. I haven’t been able to do everything he mentioned, but it looks like he got it working.

    It’s definitely a big headache to get things working.

  3. mbreese

    @Paul

    Yeah, I did find that link before. It is what gave me the idea to start looking at 64/32 bit issues. What he ultimately did to get it to work was to compile MySQL from scratch and make sure that it was built for all archs. Macs are kinda funny in that one binary can contain the same code, but compiled for to objects for different archs. It’s kinda amazing really, but it does add a whole other level of troubleshooting.

    As a side note, the person in the link above still had 64 bit issues because eventhough he had 32bit Mysql libraries he was running his Apache instance as 64bit, which caused some other problems when it spawned the python process.

    I haven’t decided yet if I’m going to compile Mysql from scratch or just install the 32bit version. Since this is a dev machine, I suspect I’ll just use the 32bit version and just be done with it.

  4. Paul Solt

    @mbreese

    Any idea on if it’s possible to package MySQL and MySQLdb with a script to give to a client who hasn’t installed MySQL or MySQLdb?

  5. mbreese

    Probably…

    I eventually did get this working (I think, I’m still writing the code, but at least I can now “import MySQLdb”). I did this by installing the x86 package as opposed to the x86_64 package. Magically everything seems to work now.

    What you should be able to do is give them a script (or an Automator workflow) that downloads the correct file, installs the MySQL package (go with the x86 version), downloads easy_install, and performs the MySQLdb install.

    This should all be able to be done as a bash script with some Automator GUI magic thrown in to make it neat and pretty.

  6. Andrew Pennebaker

    I’m getting the same errors even without trying 64bit stuff. I don’t mind debugging my own software but I hate hate hate when other people’s software fails. I’ve been cruising along with Ruby on Rails. Why should I spend the time to learn Django if every step is going to be like this? Why hasn’t Guido championed a package system akin to RubyGems? Perl has a package manager, Ruby has a package manager, even Lua has a package manager. Someone tell me if Python Eggs is that package system, because in my mind they’re nothing more than clever zip files. The main page compares them to Java’s JARS. But we need more than ever more complicated ZIPs, JARS, EGGs, and [those really stupid] WARs. It makes me wonder if there’s an ebuild for this, an RPM, a DEB, an Ubuntu repository. Argh!

  7. mbreese

    @Andrew
    You might want to look into setup tools / easy_install for a Python package manager.

    http://peak.telecommunity.com/DevCenter/setuptools

    I think you’ll find that it is very similar to RubyGems.

  8. Stu Thompson

    Ugh. I’ve just spent the past two hours dealing with this exact same scenario (on my shiny new mbp :) and am going the “move from 64-bit to 32-bit mysql local installation” option.

    Thanks for detailing this though…nice to know I’m not the only one.

    Stu

  9. jasonrbriggs

    Hmm. Just did the same thing. Spent an hour fiddling/googling because I’m trying to set MySQLdb up to work with a standard MAMP install.

    Wish I’d found this post -before- I started… sigh.

  10. tickletik

    Hi, I think I’ve finally gotten a 64-bit version of Python 2.6 compiled and working with apache, mod_python, MySQLdb and django. I’ve only done a quick django test using the first two parts of the django tutorial, but everything seems to be in order.

    I’d love it if people would check my work and let me know if it passes muster.

    (I also make an honorable mention to fourspaces)

    http://tickletik.blogspot.com/2008/12/python-and-mysql-on-64bit.html

    There’s also a post on getting Django up and running, but it’s still sketchy, I’m still fiddling with the apache conf file.

Leave a Comment