8/16/18
Introducing MySQL Connector/Python
by Jesper Krogh
When you write a program that needs to connect to a database server, you need a library that translates your queries into the messages that can be used with the protocol supported by the database. When the database is MySQL, this library is called a connector. There are connectors for several programming languages, from JavaScript (Node.js) to C++. The connector used with Python is called MySQL Connector/Python.
The standard API for using databases in Python is PEP249 – Python Database API Specification v2.0. This API is also what MySQL Connector/Python has implemented since version 1.0. The PEP249 implementation provides great support for executing queries through SQL statements.
The latest MySQL version is 8.0 and introduces a new API for MySQL called the X DevAPI. The special thing about the X DevAPI is that it is primarily a NoSQL API. It supports storing data in JSON documents (the MySQL Document Store), the use of SQL tables through a NoSQL API, and of course the execution of SQL statements. Additionally, the X DevAPI has been developed to work similarly in all supported programming languages while keeping to the traditions and conventions of each respective language.
MySQL Connector/Python 8.0 includes support both for the PEP249 API and the X DevAPI. This support gives the programmer great flexibility to choose the API that works the best for any given job. The two main modules containing the implementations are mysql.connector for the PEP249 API, and mysqlx for the X DevAPI. The following table compares the two APIs.
| PEP249 API | X DevAPI |
Module | mysql.connector | mysqlx |
First GA version | 1.0.7 | 8.0.11 |
Supports C Extension | Yes | Yes |
Main features | Standard Python API Best support for SQL statements | Modern API NoSQL Support (JSON documents and SQL tables) Limited SQL statement support |
The easiest way to describe the differences between the APIs is to look at an example. The MySQL sample database named world_x will be used to execute a SELECT in the PEP249 API and the X DevAPI, as well as a read query in the JSON document store part of the X Dev API.
Let’s start with the PEP249 API. The query finds the city with ID = 130, and returns the name, country code, district (state), and population. The population is stored in a JSON column, so the -> operator is used (the same as the JSON_EXTRACT() function). The example code is:
import mysql.connector
connect_args = {
"host": "127.0.0.1",
"port": 3306,
"user": "root",
"password": "password",
};
fmt = "{0:<6} {1:^7} {2:<15} {3:>10}"
db = mysql.connector.connect(**connect_args)
cursor = db.cursor(dictionary=True)
sql = """
SELECT Name, CountryCode, District, Info->'$.Population' AS Population
FROM world_x.city
WHERE ID = %(id)s"""
cursor.execute(sql, params={"id": 130})
row = cursor.fetchone()
print("PEP249 API:\n")
print(fmt.format("Name", "Country", "District", "Population"))
print(fmt.format(
row["Name"], row["CountryCode"], row["District"], row["Population"]))
cursor.close()
db.close()
Warning: Connection parameters including passwords are for simplicity included in my examples in this post. Never though, store passwords in your programs. Additionally, the examples are without any kind of error handling, which of course you should include in anything you write for production use.
The output of executing the program is:
PEP249 API:
Name Country District Population
Sydney AUS New South Wales 3276207
As comparison, executing the same query through the X DevAPI can be done as follows:
import mysqlx
connect_args = {
"host": '127.0.0.1',
"port": 33060,
"user": "root",
"password": "password",
};
fmt = "{0:<6} {1:^7} {2:<15} {3:>10}"
db = mysqlx.get_session(**connect_args)
schema = db.get_schema("world_x")
city = schema.get_table("city")
stmt = city.select(
"Name", "CountryCode", "District",
"Info->'$.Population' AS Population"
).where("ID = :id")
result = stmt.bind("id", 130).execute()
row = result.fetch_one()
print("X DevAPI - SQL Table:\n")
print(fmt.format("Name", "Country", "District", "Population"))
print(fmt.format(
row["Name"], row["CountryCode"], row["District"], row["Population"]))
db.close()
Notice how the connection is made to port 33060. This port number is not a mistake. The traditional MySQL protocol uses port 3306 by default. The X DevAPI uses a new protocol – the X Protocol – which by default uses port 33060.
The X DevAPI example takes advantage of the support for chaining when building the SQL statement to be executed. This use of chaining can, for example, be seen in the code starting with stmt = city.select. One difference from the PEP249 version is that you don’t pass a written-out SQL statement to theX DevAPI. Instead the statement to be executed is created for you through a series of API calls.
The world_x.city table does not qualify as a JSON document collection despite it having a JSON column. Instead, the countryinfo collection is used. The following example shows how to execute a read query against the JSON Document Store. The example is similar to the two previous examples, as it finds information for Australia (with the _id = AUS):
import mysqlx
connect_args = {
"host": '127.0.0.1',
"port": 33060,
"user": "root",
"password": "password",
};
fmt = "{0:<10} {1:^12} {2:>10}"
db = mysqlx.get_session(**connect_args)
schema = db.get_schema("world_x")
city = schema.get_collection("countryinfo")
stmt = city.find("_id = :country").fields(
"Name", "IndepYear", "demographics.Population AS Population")
result = stmt.bind("country", "AUS").execute()
doc = result.fetch_one()
print("X DevAPI - Document:\n")
print(fmt.format("Name", "Independence", "Population"))
print(fmt.format(doc["Name"], doc["IndepYear"], doc["Population"]))
db.close()
Notice when using the Document Store that you set the filtering condition in the call to find(), then add the fields using the field() method. The opposite was the case for the SQL table where the fields where specified through a call to the select() method, and the condition was set through calling the where() method. Otherwise the overall flow is similar.
If you want to explore MySQL Connector/Python on your own, there are several ways to install MySQL Connector/Python. The simplest is to use the pip command to install the mysql-connector-python package:
shell$ pip install mysql-connector-python
There are also repositories available for several Linux distributions, a MySQL Installer for Microsoft Windows, and direct downloads from https://dev.mysql.com/downloads/. The full installation instructions can be found in the MySQL Connector/Python reference manual.
About the Author
Jesper Wisborg Krogh is a member of the Oracle MySQL Support team and has spoken on several occasions at Oracle OpenWorld. He is author of the following books on MySQL:
This article was contributed by Jesper Krogh, author of MySQL Connector/Python Revealed.