MySQL, Flask, and OSX, Oh my!

MySQL, Flask, and OSX, Oh my!

I always seem to get about half-way through one of these projects and I start muttering to myself, “should just set up a Linux box for development; should just set up a Linux box for development…” Then I remember that I really like OSX for just about everything else and so here we are.

I am in the midst of updating a small flask app to move it from using sqlite to using MySQL. In addition to plain flask, I’m using the excellent peewee ORM and flask integration toolkit.

I’ve deployed my little flask-peewee application using the guidelines here. There is a config.py file[1] that contains the bits that talk to an sqlite database:

DATABASE = {
    'name': 'database.db',
    'engine': 'peewee.SqliteDatabase',
    'check_same_thread': False,
}

So, now I need to move this so that it will talk to a MySQL machine somewhere else. I should just have to make some edits to the config.py file and everything will Just Work. And that’s it! Except that it doesn’t just work, at least not on OSX. This post describes what I had to do to enable this functionality on my local MacBook Air.

First, as recommended by the developer of Flask, I’m using virtualenv for Flask. By the way, it’s assumed that your already have Xcode installed. Covering installation of Xcode is outside the scope of this note. It’s also assumed that you’ve already installed virtualenv, which allows you to manage separate installations of Python and related libraries.

Here’s a slightly modified (as in I removed all of my mistakes) transcript of the steps required to create a flask environment on my local Mac.

    $ cd ~/workspace
    $ virtualenv venv
    $ . ./venv/bin/activate
    $ pip install readline
    $ pip install ipython
    $ pip install Flask
    $ pip install flask_peewee
    $ pip install mysql-python

Everything went fine until the mysql-python part. I was greeted with a bunch of errors:

  File "setup_posix.py", line 25, in mysql_config

    raise EnvironmentError("%s not found" % (mysql_config.path,))

EnvironmentError: mysql_config not found

----------------------------------------
Cleaning up...
Command python setup.py egg_info failed with error code 1 in /private/var/folders/t1/pszd69g92mx3dpjmg66yy4mj86v7xm/T/pip_build_zippy/mysql-python
Storing complete log in /Users/zippy/Library/Logs/pip.log

First things first, I double-checked that I had MySQL installed. I did – if you don’t, just get it from MySQL. There are a number of tutorials on installing it on OSX. This one works: MacLochlainns Weblog. Really, you don’t need to run the whole MySQL server on your local machine. What you need is the MySQL client library that the mysql-python library is linked against. On we go… simply installing this package will not fix your issue.

For that, we need two more magic bits. First, we need to fix the path to the mysql_config file. After the build fails, visit venv/build/mysql-python and edit site.cfg. Add a line that says mysql_config = /usr/local/mysql/bin/mysql_config. You can also uncomment the existing commented out line as a starting point, but note that the path that it references is not correct for OSX. You will need to edit it as above.

Retry the installation with pip install mysql-python. It will appear to succeed; however, we are not quite done. We now have to perform some more OSX library linking and renaming magic. A number of solutions are mentioned here on stack overflow. My favorite solution was not the one with the winning number of votes, but it felt like the best one. It’s the one proposed by Caleb Shay and got 33 votes. You use otool and install_name_tool to fix the invalid reference in _mysql.so in your virtualenv Python. Once that’s done, you’re all set.

In my case, I ran this:

cd venv/lib/python2.7/site-packages
install_name_tool -change libmysqlclient.18.dylib /usr/local/mysql/lib/libmysqlclient.18.dylib _mysql.so

And that was it. I’ve now told the local _mysql.so that it should look for the mysqlclient library in a specified location. I haven’t affected anything system-wide, but I am now able to use the MySQL back-end in flask-peewee.

Finally, here’s is the working configuration from config.py that allows me to connect to my remote MySQL database server:

   DATABASE = {
         'name': 'our_apps',
         'engine': 'peewee.MySQLDatabase',
         'host': 'serverserver.law.emory.edu',
         'port': 3306,
         'user': 'noah',
         'passwd': 'CHANG3M3',
     }

And at the end, it was very anti-climactic. The app just worked even though it was now hitting a remote MySQL database server as opposed to using a local SQLite data file.


  1. If you read the referenced article, Mr. Leifer doesn’t really reference the need for config.py, but that’s what the line app.config.from_object('config.Configuration') does – it calls config.py for configuration. See more detail here.  ↩

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s