3

I finally resolved the ubiquitous MySQL-python/OSX (10.7 64-bit) debacle and have Python and MySQL working fine by using 32-bit MySQL and calling python with 'arch -i386'. Py scripts outside of Django are correctly querying MySQL etc. However, when I try to fire up Django and invoke the development server, I'm getting the error I was getting previously when using 64-bit Python:

django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: dlopen(/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/_mysql.so, 2): no suitable image found.  Did find:
    /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/_mysql.so: mach-o, but wrong architecture

In my .bash_profile I have

alias python='arch -i386 python2.7'

export VERSIONER_PYTHON_PREFER_64_BIT=no

export VERSIONER_PYTHON_PREFER_32_BIT=yes

So I don't understand how Django is invoking python and why it isn't honoring what I have in .bash_profile. What do I need to change in Django to get it to invoke 32-bit Python? The full traceback when I do 'python manage.py runserver' is:

Traceback (most recent call last):
  File "manage.py", line 14, in <module>
    execute_manager(settings)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 438, in execute_manager
    utility.execute()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/base.py", line 191, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/base.py", line 209, in execute
    translation.activate('en-us')
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/translation/__init__.py", line 100, in activate
    return _trans.activate(language)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 202, in activate
    _active.value = translation(language)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 185, in translation
    default_translation = _fetch(settings.LANGUAGE_CODE)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 162, in _fetch
    app = import_module(appname)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/admin/__init__.py", line 3, in <module>
    from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/admin/helpers.py", line 3, in <module>
    from django.contrib.admin.util import (flatten_fieldsets, lookup_field,
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/admin/util.py", line 1, in <module>
    from django.db import models
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/__init__.py", line 78, in <module>
    connection = connections[DEFAULT_DB_ALIAS]
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/utils.py", line 93, in __getitem__
    backend = load_backend(db['ENGINE'])
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/utils.py", line 33, in load_backend
    return import_module('.base', backend_name)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 14, in <module>
    raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e)
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: dlopen(/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/_mysql.so, 2): no suitable image found.  Did find:
        /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/_mysql.so: mach-o, but wrong architecture
Community
  • 1
  • 1
kasceled
  • 548
  • 1
  • 6
  • 18

2 Answers2

1

The VERSIONER_PYTHON_PREFER_32_BIT environment variable is an Apple-supplied feature. It only applies to the Apple-supplied system Pythons in Mac OS X 10.6 and 10.7. From the path shown, you are using a non-system Python (installed in /Library/Frameworks, possibly from a python.org installer). VERSIONER_PYTHON_PREFER_32_BIT will have no affect on it. Have you tried launching the development server with something like:

arch -i386 /usr/local/bin/python2.7 django-admin.py ...

You still may run into trouble if Django launches Python interpreters in subprocesses which will default to 64-bit. You should either get everything working in 64-bit mode or stick to a complete 32-bit chain of Python and MySQLdb. You could save yourself a lot of trouble by installing a complete solution from a third-party distributor like MacPorts or Homebrew.

Ned Deily
  • 83,389
  • 16
  • 128
  • 151
0

I had a similar issue with Snow Leopard, but was using a virtual environment for all my work. If you're using one too (which is the recommended way to work with Django), then you can force the version of python your virtual environment uses. When you create a new virtual environment, just say something like:

virtualenv --python=/Library/Frameworks/Python.framework/Versions/2.7/bin/python new-environment
Spike
  • 5,040
  • 5
  • 32
  • 47
  • This seems to be the best route to go, but after creating the virtualenv and specifying the custom python path, I'm still getting basically the same issue, which doesn't make sense to me. In the virtualenv, after lipo'ing the python executable to get rid of x86_64, I fire up interactive shell and verify that sys.maxint gives the 32-bit number. In the shell, I can 'import MySQLdb' and 'import _mysql' with no errors. But exiting the python shell and running 'python manage.py runserver' gives me the _mysql.so 'wrong architecture' error in the Traceback on the OP. Makes no sense to me. – kasceled Sep 15 '11 at 20:37
  • This lipo workaround was via the SO thread [here](http://stackoverflow.com/questions/2088569/how-do-i-force-python-to-be-32-bit-on-snow-leopard-and-other-32-bit-64-bit-questi), by user Cogg – kasceled Sep 15 '11 at 20:45
  • 1
    hmm. If you're not tied to MySQL, I'd suggest moving over to Postgres, since that's what the Django developers recommend anyway. I ran into various issues with MySQL while using it for a few months, and I am now happy with my decision to migrate to Postgres. – Spike Sep 15 '11 at 21:18