Wednesday, December 20, 2006

Python MySQLdb, warnings, mix-ins

I've been working on a side project that uses MySQLdb. Database work. Munging imperfect data inevitably spawns warnings and I want to supress the obviously unimportant ones.

Originally, one would call MySQLdb.connect with "cursorclass=MySQLdb.cursors.CursorNW" as an argument. (NW=No Warnings). That hasn't worked for years, though, so if you google and find that, you're SOL.

The next approach was to derive a new cursor class using mix-ins; the default cursor has a "Warning" mix-in that we simply want to exclude:

import MySQLdb.cursors
class EricsCursor(MySQLdb.cursors.CursorStoreResultMixIn,
MySQLdb.cursors.CursorTupleRowsMixIn,
MySQLdb.cursors.BaseCursor,
):
...
db = MySQLdb.Connect( user=uname, passwd=pword, db=dbase, cursorclass=EricsCursor)

Unfortunately, that documentation is also out of date. The CursorWarningMixIn is no more and in fact the EricsCursor is exactly what the default cursor is, now. So that doesn't work either... still SOL.

Finally, the actual, correct way to supress these messages is with the stock python warning module. You can either turn off all warnings (which is probably a bad idea) or filter exactly those you know are incorrect out, as follows:

import warnings
Class Blah:
def supress_warnings():
# I get a warning on "DROP TABLE IF EXISTS" query,
# that the temp table (something_temp) is unknown.
warnings.filterwarnings("ignore", "Unknown table.*_temp")
return
supress_warnings = staticmethod(supress_warnings)


This actually works, and I can piecewise supress any warnings I know are irrelevant. I made it a static method to keep the code in the same module as the Database class, but I want to call it exactly once early in my program initialization routines.

3 comments:

Lindsey said...

thanks, this was v. helpful

RedGlow said...

Thank you! Exactly what I was looking for a test suite I'm writing!

Evan Siroky said...

Ah, good idea. Here is a snippet of what I wrote:

with warnings.catch_warnings():
warnings.filterwarnings('ignore',"Field.*doesn't have a default value")
cursor.execute(insertQ)