3am is when the world is most interesting.
Random header image... Refresh for more!

Python MySQLdb snippet

So, for the past few weeks, I’ve been hacking around with Python’s MySQLdb DBAPI v2 driver. After getting so used to mysqli in PHP, the move to MySQLdb was a mixed bag – some things are awesome, others not so much.

First the awesome – it’s so much cleaner to do safe, simple queries with python’s dbapi, than with the PHP mysqli stuff. Just call cursor.execute(query, arguments) and pass in your SQL and it’s arguments, and all the escaping and safety stuff is taken care of behind the scenes. No ugly hacks to check to see if something is a digit or a string and to properly escape/format the final query for you. In addition to that, connecting and setting the character set and forcing the driver to use unicode is all just 2 little options passed in the connect() method.

Now, the not so awesome – I really liked mysqli_fetch_assoc() for returning data from the database in a easy to use form – an associate array (in case it wasn’t obvious!). DBAPI drivers for python do not provide such a feature out of the box – your data comes back as a tuple, rather than a dict. While this makes some sense, the lack of a way to get a dict back seems to be rather un-pythonic. It violates the ‘Explicit is better than implicit’ and ‘Beautiful is better than ugly’ Zen of Python aphorisms. It requires implicit accessing of your data, as you must use tuple slices/subscripts instead of keywords to the dict, and that requires ugly numbers dropped into the otherwise easily readable code.

In an effort to save myself some trouble, here’s a quick way to emulate the fetch_assoc functionality, built in to a generator function so it can be used easily in ‘for’ statements and the like:

#!/usr/bin/env python
# Requires a version of python that supports generator functions (2.3+)
import  MySQLdb

connection = MySQLdb.connect(host="localhost", user="username", passwd="passwd", db="myInstance", use_unicode=True, charset="utf8")
cursor = connection.cursor()
def query(query, args):
        numRows = cursor.execute(query, args)
        tries = 0
        dbKeys = cursor.description
        row = {}
        while tries < numRows:
                tries = tries + 1
                dbRow = cursor.fetchone()
                for item, key in zip(dbRow, dbKeys):
                        row[key[0]] = item
                yield row

sql = """SELECT foo, bar FROM baz WHERE id = %(id)s"""
args = {'id':'adam'}

for rows in query(sql, args):
        print rows

That outputs:

	{'foo': u'fooValue', 'bar':'barValue'}
	{'foo': u'fooValue2', 'bar':'barValue2'}

7 comments

1 Andrew RevakNo Gravatar { 01.25.08 at 6:23 pm }

You know I went to python from PHP and had that complaint too, then I found out about cursor types. MySQLdb for python supports a vast array of cursor types but the one you will probably be the most interested in is DictCursor

MySQLdb.cursors.DictCursor

just issue

import MySQLdb
from MySQldb.cursors import *

to get yourself setup.

More here: http://mysql-python.sourceforge.net/MySQLdb-1.2.2/public/MySQLdb.cursors.DictCursor-class.html

2 adamNo Gravatar { 01.25.08 at 6:24 pm }

I KNEW there had to be a way! Oh well, I got to write some fun code and play with generators.
Thanks!

3 Andrew RevakNo Gravatar { 01.25.08 at 6:29 pm }

Yea heh I basically did the same thing you did before reading father in my oreilly book cause I said wow i defintily need this feature and its not immediatly apparent.

4 kmNo Gravatar { 07.14.08 at 6:46 pm }

I just needed this tips.
We wish to express our gratitude to you!

5 Ni2No Gravatar { 01.14.09 at 4:43 am }

import MySQLdb

Connection = MySQLdb.connect(host=”, port=”, user=”,passwd=”, db=”, cursorclass=MySQLdb.cursors.DictCursor)

Cursor = Connection.cursor()
sql = “SELECT FieldA, FieldB, FieldC FROM table”
Cursor.execute(sql)

results = Cursor.fetchone()

>>>print results
{‘FieldA’: ‘My field a values’, ‘FieldB’: ‘My field b values’}

>>>print results['FieldA']
‘My fields a values’

6 adamNo Gravatar { 02.01.09 at 4:58 pm }

Yeah, I discovered this AFTER I wrote my function :) Thanks though.

7 Travis LowNo Gravatar { 02.27.09 at 4:27 am }

Does anyone know how to use “like” ? This is making me nuts in python, it would be a 30-second job in any other language I’ve ever used.

title = “some old title”
sql = “select id from blah where title like %s”
cursor.execute(sql,(‘%’+title+’%'))

My problem is that it’s not working, and I don’t know how to ask the cursor object for the SQL that it actually *is* executing, so how can I ever find out what’s wrong? I did try the obvious query on the mysql command line and it does what I want it to: select id from blah where title like ‘%some old title%’

ARRRRRRRGGGGGHHH

Thanks in advance for any help.

Leave a Comment