segunda-feira, 16 de dezembro de 2013

Automagically convert Python objects to MySQL

in http://www.jejik.com/articles/2007/04/automagically_convert_python_objects_to_mysql/

Automagically convert Python objects to MySQL

by Sander Marechal
I recently ran into an annoying little snag when using MySQL. Apparently MySQL cannot handle ISO 8601 datetime values such as used by XML-RPC that use the format YYYYMMDDTHH:MM:SS. MySQL will simply convert such values to 0000-00-00 00:00:00 with a warning. I have reported this bugto MySQL but I was still faced with the unpleasant prospect of converting all my XML-RPC dateTime values to something MySQL could understand.
I searched for a way to do this automatically and I came across a way tucked inside the MySQLdb Python module. MySQLdb contains a map of conversion functions and datatypes between MySQL's column types and Python's datatypes. It is possible to extend this list and pass it to the connect() method and have any datatype supported that you want. If you don't care for the details and just want to see the code, just skip to the end.
In MySQLdb.converters.py you can find a map called conversions that simply maps Python datatypes to a converter function and MySQL column types to Python types. Type conversion happens with the use of this map whenever you qyery the database for results or whenever you insert Python variables in SQL queries using the DB API's format. If a conversion for a Python type to a MySQL type cannot be found, MySQLdb simply tries to call that object's __str__() method and tries to use that result instead.
Now you can see where my problem came in: the DateTime type used in xmlrpclib is not in MySQLdb's conversion map, and the DateTime's __str__()method returned a format of YYYYMMDDTHH:MM:SS.
To convert your own datatype automatically to something MySQL can handle, you need to define a function that will accept as arguments the object you want to convert and a dictionary. You don't need the dictionary usually but it's a required argument nonetheless. And here's the code that shows how I did this for xmlrpclib's DateTime:
  1. #!/usr/bin/env python
  2. import MySQLdb
  3. import MySQLdb.converters
  4. from xmlrpclib import DateTime
  5. # define the DateTime conversion
  6. def DateTime2string(objectdict):
  7.     iso = object.__str__()
  8.     sql = iso[0:4] + '-' + iso[4:6] + '-' + iso[6:]
  9.     # properly escape the value when returning
  10.     return MySQLdb.converters.Thing2Literal(sql, dict)
  11. # get the conversion table
  12. conv_dict = MySQLdb.converters.conversions
  13. conv_dict[DateTime] = DateTime2string
  14. # connect to the server with the new conversion table
  15. db = MySQLdb.connect(
  16.     host='localhost',
  17.     user='username',
  18.     passwd='password',
  19.     db='database',
  20.     conv=conv_dict
  21. )
And that's all there is to it! You can convert any kind of object to a proper MySQL string representation this way. Happy coding!
Creative Commons Attribution-ShareAlike

Sem comentários: