Compiling mysqlclient for Python 2.7 on Windows 7 and up

I recently wanted to get into Django. I wanted to be able to go back between my real webserver and local development quickly, so I chose MySQL as my database. I quickly discovered that the recommended way is to use mysqlclient. Unfortunately, trying to install it using pip fails outright:

> pip install mysqlclient

You’ll be greeted by the following error message:

Collecting mysqlclient
  Downloading mysqlclient-1.3.12.tar.gz (89kB)
    100% |################################| 92kB 535kB/s
Installing collected packages: mysqlclient
  Running setup.py install for mysqlclient ... error
    Complete output from command c:\python27\python.exe -u -c "import setuptools, tokenize;__file__='c:\\users\\robert\\appdata\\local\\temp\\pip-build-nveaxr\\mysqlclient\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record c:\users\robert\appdata\local\temp\pip-t504mt-record\install-record.txt
 --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    creating build
    creating build\lib.win-amd64-2.7
    copying _mysql_exceptions.py -> build\lib.win-amd64-2.7
    creating build\lib.win-amd64-2.7\MySQLdb
    copying MySQLdb\__init__.py -> build\lib.win-amd64-2.7\MySQLdb
    copying MySQLdb\compat.py -> build\lib.win-amd64-2.7\MySQLdb
    copying MySQLdb\connections.py -> build\lib.win-amd64-2.7\MySQLdb
    copying MySQLdb\converters.py -> build\lib.win-amd64-2.7\MySQLdb
    copying MySQLdb\cursors.py -> build\lib.win-amd64-2.7\MySQLdb
    copying MySQLdb\release.py -> build\lib.win-amd64-2.7\MySQLdb
    copying MySQLdb\times.py -> build\lib.win-amd64-2.7\MySQLdb
    creating build\lib.win-amd64-2.7\MySQLdb\constants
    copying MySQLdb\constants\__init__.py -> build\lib.win-amd64-2.7\MySQLdb\constants
    copying MySQLdb\constants\CLIENT.py -> build\lib.win-amd64-2.7\MySQLdb\constants
    copying MySQLdb\constants\CR.py -> build\lib.win-amd64-2.7\MySQLdb\constants
    copying MySQLdb\constants\ER.py -> build\lib.win-amd64-2.7\MySQLdb\constants
    copying MySQLdb\constants\FIELD_TYPE.py -> build\lib.win-amd64-2.7\MySQLdb\constants
    copying MySQLdb\constants\FLAG.py -> build\lib.win-amd64-2.7\MySQLdb\constants
    copying MySQLdb\constants\REFRESH.py -> build\lib.win-amd64-2.7\MySQLdb\constants
    running build_ext
    building '_mysql' extension
    error: Microsoft Visual C++ 9.0 is required. Get it from http://aka.ms/vcpython27
 
    ----------------------------------------
Command "c:\python27\python.exe -u -c "import setuptools, tokenize;__file__='c:\\users\\robert\\appdata\\local\\temp\\pip-build-nveaxr\\mysqlclient\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record c:\users\robert\appdata\local\temp\pip-t504mt-record\install-record.txt --single-version-externally-managed --compile" failed with error code 1 in c:\users\robert\appdata\local\temp\pip-build-nveaxr\mysqlclient\

There is of course an easy solution: don’t. Instead use a pre-compiled binary wheel by Some Guy on the Internetโ„ข. No disrespect to the maintainer of the site, Christoph Gohlke. It merely speaks volumes about the state of things when open-source availability is binary-only, because compilation is undocumented/fraught with issues.

Since I didn’t find a complete and straightforward guide online, I’ll post the way I did it here. I’ll document various errors that might pop up along the way (or at least did for me) in case somebody else runs into them. Briefly put, I did the following:

  1. Download the Oracle MySQL C Connector source code.
  2. Download and install a Microsoft C Compiler:
    1. Visual Studio 9 2008; Visual C++ 2008 Express will do.
    2. Microsoft Visual C++ Compiler for Python 2.7 will do in a real pinch.
  3. (VS9 only) Download and install Microsoft Windows SDK for Windows 7 (v7.0 or v7.1) and use the Windows SDK Configuration Tool to reconfigure Visual Studio to use the Windows 7 SDK.
  4. Use CMake to generate Makefiles for the MySQL C Connector source code.
  5. Compile the MySQL C Connector mysqlclient library.
  6. Install the MySQL C Connector binary and add the compiled mysqlclient.
  7. Run pip install mysqlclient again.

1. Get the Oracle MySQL C Connector

First things first. You won’t get a recent MySQL C Connector compiled for Visual Studio 9 — which is the version Python 2.7 is compatible with — so you’ll have to compile from source yourself.
See the Python Wiki for more information.

Go to dev.mysql.com/downloads/connector/c/6.1.html and download both source code and binary installer for the architecture of your choice. This architecture should match Python 2.7, so if you installed a 64-bit Python, you’ll want the winx64 packages. Use win32 packages for a 32-bit Python.

You should end up with mysql-connector-c-6.1.11-src.zip and mysql-connector-c-6.1.11-win32.msi or mysql-connector-c-6.1.11-winx64.msi respectively. If you’re unsure which version of Python is installed, open Python and check the output of

import platform
platform.architecture()

If the final architectures don’t match, you’ll get the following error in step 7:

python27.lib(python27.dll) : fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'X86'

2. Download and install a Microsoft C Compiler

I strongly recommend using a full Visual Studio 9, because it’s just more useful in general. However, the Microsoft Visual C++ Compiler for Python 2.7 works, too, if you figure out how to get CMake to cooperate.

Get Visual C++ 2008 Express from go.microsoft.com/?linkid=7729279 if you don’t have a full Visual Studio 2008 lying around.
Use Microsoft Visual C++ Compiler for Python 2.7 from aka.ms/vcpython27. Make sure to follow the Python Wiki installation instruction and call the MSI using msiexec /i ALLUSERS=1 if you can, or else it will install to C:\Users\Name\AppData instead of C:\Program Files.

3. (VS9 only) Download and install Microsoft Windows SDK for Windows 7

Skip this step if you don’t use Visual Studio 9.

In order to use Slim Reader/Writer (SRW) Locks, you will have to update the SDK to Windows 7, because Visual Studio 9 still defaults to Windows Vista.
Grab either v7.0 of the SDK from www.microsoft.com/en-us/download/details.aspx?id=18950 or v7.1 from www.microsoft.com/en-us/download/details.aspx?id=8279.

Use the included Windows SDK Configuration Tool (in the Start Menu under Visual Studio Registration) to change to a v7 SDK:

If you forget this step, you’ll have lots of warnings complaining about SRW functions later on:

21>..\..\mysql-connector-c-6.1.11-src\mysql-connector-c-6.1.11-src\include\thr_rwlock.h(86) : warning C4013: 'TryAcquireSRWLockShared' undefined; assuming extern returning int
21>..\..\mysql-connector-c-6.1.11-src\mysql-connector-c-6.1.11-src\include\thr_rwlock.h(108) : warning C4013: 'TryAcquireSRWLockExclusive' undefined; assuming extern returning int

4. Create Makefiles using CMake

Use CMake from cmake.org to generate a suitable Visual Studio Project (VS9) or NMake Makefile from the extracted source directory mysql-connector-c-6.1.11-src. Be sure to select the appropriate CMAKE_BUILD_TYPE, probably Release.

4a. When using Visual Studio 9 2008

Use either cmake-gui or the command line cmake utility to create suitable project files.
Select “Visual Studio 9 2008”.

4b. When using Microsoft Visual C++ Compiler for Python 2.7

Microsoft Visual C++ Compiler for Python 2.7 doesn’t come with the usual make tools provided by Visual Studio. Instead, it provides NMake, so you’ll have to select “NMake Makefiles” in CMake instead. This comment on a Github Issue goes into a bit more detail.

Be sure to open a command prompt in C:\Program Files (x86)\Common Files\Microsoft\Visual C++ for Python\9.0 and issue vcvarsall.bat x86 or vcvarsall.bat x64 depending on your target architecture. Then use cmake. Then navigate to the cmake build directory using that command prompt. Using the vcvars32.bat or vcvars64.bat batch files did not work for me for some reason.

5. Compile MySQL Client

Before compiling you’ll need to address two more issues with the standard library supplied by Microsoft.

5a. C99 Integer Types

The standard integer types are missing from Microsoft’s headers. You would encounter the following error:

12>..\..\mysql-connector-c-6.1.11-src\mysys_ssl\crypt_genhash_impl.cc(34) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory

You’ll need a C99-compliant copy of the stdint.h and inttypes.h headers (and optionally the stdlib.h header, see below) either from a more recent version of Visual C++ (2013 or 2015 work) or you can use the freely available msinttypes headers, see this StackOverflow post.

5b. Long Division Result Type

If you didn’t install stdlib.h along with stdint.h and inttypes.h then you’ll be missing the lldiv_t type:

2>..\..\mysql-connector-c-6.1.11-src\include\decimal.h(64) : error C2143: syntax error : missing ')' before '*'
2>..\..\mysql-connector-c-6.1.11-src\include\decimal.h(64) : error C2081: 'lldiv_t' : name in formal parameter list illegal
2>..\..\mysql-connector-c-6.1.11-src\include\decimal.h(64) : error C2143: syntax error : missing '{' before '*'
2>..\..\mysql-connector-c-6.1.11-src\include\decimal.h(64) : error C2059: syntax error : ')'

Either copy stdlib.h from Visual C++ 2013 or Visual C++ 2015 or copy-paste the following definition to the top of decimal.h:

typedef struct {
long long quot;
long long rem;
} lldiv_t;

5c. Compile mysqlclient

If you’re on Visual Studio 9, then just open the generated LibMySQL.sln solution file and build mysqlclient.

If you use NMake, then open a command line in the CMake build directory, do all the variable setup like in step 4, and then issue nmake mysqlclient.

Now you have hopefully successfully built the client library the Python package needs.

6. Combine mysqlclient.lib with MySQL C Connector

Install the MSI installer for the MySQL C Connector you downloaded in step 2. We will combine the official binary distribution with our newly-generated library in this step. First, we’ll have to take care of a Python package issue, however:

Regardless of Python architecture, the mysqlclient setup script uses a hard-coded library path to find the MySQL Client library: "/LIBPATH:C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\lib\vs9".

The resulting errors reported by pip are:

_mysql.c(29) : fatal error C1083: Cannot open include file: 'mysql.h': No such file or directory
LINK : fatal error LNK1181: cannot open input file 'mysqlclient.lib'

among others depending on the exact directory layout, I presume.

Temporarily move the MySQL C Connector directory to C:\Program Files (x86)\MySQL\MySQL Connector C 6.1. Then locate mysqlclient.lib in the CMake build directory and copy it into the vs9 subdirectory you’ll create in the lib directory: C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\lib\vs9. This is where the mysqlclient Python package looks for the library.

7. Re-run pip

Finally, re-run pip, like so:

>pip install mysqlclient
Collecting mysqlclient
  Using cached mysqlclient-1.3.12.tar.gz
Installing collected packages: mysqlclient
  Running setup.py install for mysqlclient ... done
Successfully installed mysqlclient-1.3.12

That’s it! All done ๐Ÿ™‚ Happy hacking ๐Ÿ˜€

I tested both ways in a Windows 7 64-bit virtual machine. I tested both 32- and 64-bit Python 2.7 and library using Visual Studio 9 and only 64-bit using Visual C++ for Python 2.7 using Oracle’s Community Edition MySQL server. That’s when I incidentally noticed a bug using row_tell and row_seek and filed a pull request ๐Ÿ˜‰

3 thoughts on “Compiling mysqlclient for Python 2.7 on Windows 7 and up

  1. papin

    Hi,
    There is a much simpler way for python 2.7.
    Go to: https://github.com/PyMySQL/mysqlclient-python/issues/54
    Search for the post by user “methane” Oct 2, 2016. methane is the author of the wheels for python 2.7. The link to the files is given in his post. Download the file corresponding to your OS and install:
    > pip install mysqlclient-1.3.9-cp27-cp27m-win32.whl

    Reply
  2. papin

    Hi,
    There is a much simpler way for python 2.7. And no prerequisites…
    Go to: https://github.com/PyMySQL/mysqlclient-python/issues/54
    Search for the post by user “methane” Oct 2, 2016. methane is the author of the wheels for python 2.7. Links to the files are given in his post. Download the file corresponding to your OS and install:

    > pip install mysqlclient-1.3.9-cp27-cp27m-win32.whl
    Processing .\mysqlclient-1.3.9-cp27-cp27m-win32.whl
    Installing collected packages: mysqlclient
    Successfully installed mysqlclient-1.3.9

    This solved an issue with “Visual C++ for Python”:
    MySQLdb/_mysql.c(29) : fatal error C1083: Cannot open include file: ‘mysql.h’: No such file or directory

    Reply
  3. Robert Abel Post author

    Hey papin,

    thanks for your feedback ๐Ÿ˜€ I linked to a similar solution as you did in my post, binary wheel distributions by Christoph Gohlke of University of California, Irvine. The point is that one shouldn’t solely rely on random users on the internet to get pre-compiled versions as they can contain bugs/incompatibilities (32-bit vs 64-bit mysql adapter for instance) or nasty viruses.

    Regards,

    Robert

    Reply

Leave a Reply to Robert Abel Cancel reply

Your email address will not be published. Required fields are marked *