MySQL and Python3

MySQL and Python Logos

I’m using Python more and more so it’s not surprising that recently the need arose to connect to and insert into a MySQL database. I was using (and usually do) Python3, and I ran into a couple of issues in the begining. This post will document those issues and the solutions I found to get MySQL and Python3 to work together.

Package Installation

Support for MySQL doesn’t ship with the Python installer, therefore we need to install a package that adds this functionality. I usually use pip3 for this task, and I tried the following.

pip3 install MySQLdb

I found code examples online showing import MySQLdb statements, so I figured that was the name of the package. I was wrong.

Could not find a version that satisfies the requirement MySQLdb (from versions: )
No matching distribution found for MySQLdb

So I thought, let’s try just pip3 install mysql

Collecting mysql
  Using cached https://files.pythonhosted.org/packages/06/ef/c4efbf2a51fb46aba9be03a973638d9539c9ca10a5259b2cbb1a66133b2e/mysql-0.0.1.tar.gz
Collecting MySQL-python (from mysql)
  Using cached https://files.pythonhosted.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip
Installing collected packages: MySQL-python, mysql
  Running setup.py install for MySQL-python ... error
    Complete output from command "c:\program files\python36\python.exe" -u -c "import setuptools, tokenize;__file__='C:\\Users\\admin\\AppData\\Local\\Temp\\pip-install-88jce1si\\MySQL-python\\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\admin\AppData\Local\Temp\pip-record-f7l848e_\install-record.txt --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    creating build
[omitted output]
    building '_mysql' extension
    creating build\temp.win-amd64-3.6
    creating build\temp.win-amd64-3.6\Release
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\bin\HostX64\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MT -Dversion_info=(1,2,5,'final',1) -D__version__=1.2.5 "-IC:\Program Files (x86)\MySQL\MySQL Connector C 6.0.2\include" "-Ic:\program files\python36\include" "-Ic:\program files\python36\include" "-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\Include" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\winrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\include\um" /Tc_mysql.c /Fobuild\temp.win-amd64-3.6\Release\_mysql.obj /Zl
    _mysql.c
    _mysql.c(42): fatal error C1083: Cannot open include file: 'config-win.h': No such file or directory
    error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.12.25827\\bin\\HostX64\\x64\\cl.exe' failed with exit status 2

Okay this is more like it, but now I’m receiving an error instead of installing a package.

The Python MySQL cl.exe Distraction

Searching the error error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.12.25827\\bin\\HostX64\\x64\\cl.exe' failed with exit status 2 and I learned that cl.exe is the Visual C++ compiler.

Apparently, the installation of the compiler is done via Visual Studio. I have Visual Studio installed so I loaded up the Visual Studio Installer – the program used to add functionality to VS. Sure enough, I didn’t have the Visual C++ components installed. I started installing it. It was taking awhile because the installation size was over 1 GB. While that was going on I continued to research MySQL and Python3. Before the process finished, I learned that the MySQLdb was not designed for Python3; the functionality was replaced by the mysqlclient package.

The Right Package (mysqlclient)

Now knowing that MySQLdb was out and mysqlclient was in, I went ahead and installed that package.

pip3 install mysqlclient
Collecting mysqlclient
  Using cached https://files.pythonhosted.org/packages/32/4b/a675941221b6e796efbb48c80a746b7e6fdf7a51757e8051a0bf32114471/mysqlclient-1.3.12-cp36-cp36m-win_amd64.whl
Installing collected packages: mysqlclient
Successfully installed mysqlclient-1.3.12

Example CRUD Operations

Now that the right MySQL package is installed, let’s do some basic Create, Read, Update, and Delete (CRUD) operations.

Create

The following example opens a CSV file containing records of gold PRICE on a given day (TIMESTAMP) from a given SOURCE.

import MySQLdb as mdb

PRICE     = 0
TIMESTAMP = 1
SOURCE    = 2

conn = mdb.connect('hostname', 'username', 'p@s$w0rd', 'database')
cursor = conn.cursor()

with open('gold_price.csv', 'r') as gold_prices:
    lines = gold_prices.read().splitlines()

    for i in range(1, len(lines)):
        _tuple = lines[i].split(',')
        cursor.execute("INSERT INTO gold_price (price, time, source) VALUES (%s, '%s', '%s');" %
        (_tuple[PRICE], _tuple[TIMESTAMP], _tuple[SOURCE]))

cursor.close()
conn.commit()
conn.close()

Retrieve

This bit fetches all the rows in a table (i.e. gold_price) and prints out each row – as a tuple.

import MySQLdb as mdb

conn = mdb.connect('www.jasonfavrod.com', 'econ', 'i8peanut$', 'econ')
cursor = conn.cursor()

cursor.execute('SELECT * FROM gold_price;')

for row in cursor.fetchall():
    print(row)

cursor.close()
conn.close()
# Output
(1319.03, 'https://www.xe.com/currencyconverter/convert/?Amount=1&From=XAU&To=USD', datetime.datetime(2018, 5, 12, 19, 30, 2))
(1313.33, 'https://www.xe.com/currencyconverter/convert/?Amount=1&From=XAU&To=USD', datetime.datetime(2018, 5, 14, 21, 0, 3))
(1290.68, 'https://www.xe.com/currencyconverter/convert/?Amount=1&From=XAU&To=USD', datetime.datetime(2018, 5, 15, 21, 0, 3))
[output omited]

Update

Here I’ll update the gold price on a give date to $1300.

import MySQLdb as mdb

conn = mdb.connect('www.jasonfavrod.com', 'econ', 'i8peanut$', 'econ')
cursor = conn.cursor()

cursor.execute("UPDATE gold_price SET price = %s WHERE time = %s", ("1300", "2018.05.15-21:00:03"))
cursor.close()
conn.commit()
conn.close()

Delete

Now we can delete that altered entry.

import MySQLdb as mdb

conn = mdb.connect('www.jasonfavrod.com', 'econ', 'i8peanut$', 'econ')
cursor = conn.cursor()


cursor.execute("DELETE from gold_price WHERE time = '%s'" % "2018-05-23 02:56:07")
cursor.close()
conn.commit()
conn.close()

For more on the mysqlclient for Python3, see their Github project.

Leave a Reply

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