MySQLdb troubleshooting Hin und wieder kommen im Forum Fragen und Probleme rund um das MySQL Modul 'MySQLdb' vor. Gerade die unicode Unterstützung brachte so einige Probleme mit sich. Hier auf der Seite sollen einfach ein paar Hinweise dazu gesammelt werden.

MySQLdb

Versionswirrwarr

Man kann meinen die Versionierung ist etwas Wirr. Wenn man sich aber mal die Downloadseite ansieht (oder auch die PyPi Seite), dann wird einem einiges klarer:

(Stand 14.09.2012)

Anscheinend ist es also so, das Versionen mit anhängen wie "a", "b", "c" testversionen sind. Versionen ohne Anhänge und mit "p" (wahrscheinlich von Patch) sind stable releases.

Unicode Ärger

Während der Entwicklung von MySQLdb, aber auch dem MySQL Server, gab es einige Änderungen im Zusammenhang mit dem Encoding. Wenn man also nicht die Möglichkeit hat, aktuelle Modul und Server Version einzusetzen, muss man sich damit auseinandersetzten.

Hier Beispiele für work-a-rounds:

django

Die django Entwickler setzten MySQLdb in v1.2.1p2 vorraus, damit alles voll funktioniert.

Es gab allerdings auch noch das sog. mysql_old backend, welches mit v1.2.0 funktioniert.

aus ./django/db/backends/mysql_old/base.py

   1 ...
   2 if self.connection.get_server_info() >= '4.1' and not self.connection.character_set_name().startswith('utf8'):
   3     if hasattr(self.connection, 'charset'):
   4         # MySQLdb < 1.2.1 backwards-compat hacks.
   5         conn = self.connection
   6         cursor.execute("SET NAMES 'utf8'")
   7         cursor.execute("SET CHARACTER SET 'utf8'")
   8         to_str = lambda u, dummy=None, c=conn: c.literal(u.encode('utf-8'))
   9         conn.converter[unicode] = to_str
  10     else:
  11         self.connection.set_character_set('utf8')
  12 
  13 ...

Die django Entwickler nutzten nicht den use_unicode Parameter beim connect. Dazu schreiben sie:

Note: use_unicode intentonally not set to work around some backwards-compat issues. We do it manually.

Das django mysql_old Modul funktioniert aber anscheinend nicht in allen Fällen, siehe:

trac

Die trac Entwickler gehen einen etwas anderen Weg. Sie setzten MySQLdb v1.2.2 vorraus.

aus ./trac/db/mysql_backend.py:

   1 ...
   2 def _set_character_set(self, cnx, charset):
   3     vers = tuple( int(n) for n in cnx.get_server_info().split('.')[:2] )
   4     if vers < (4, 1):
   5         raise TracError, 'MySQL servers older than 4.1 are not supported!'
   6     cnx.query('SET NAMES %s' % charset)
   7     cnx.store_result()
   8     cnx.charset = charset
   9 
  10 def __init__(self, path, user=None, password=None, host=None,
  11              port=None, params={}):
  12     import MySQLdb
  13 
  14     # python-mysqldb 1.2.1 added a 'charset' arg that is required for
  15     # unicode stuff.  We hack around that here for older versions; at
  16     # some point, this hack should be removed, and a strict requirement
  17     # on 1.2.1 made.  -dilinger
  18     if self._mysqldb_gt_or_eq((1, 2, 1)):
  19         cnx = MySQLdb.connect(db=path, user=user, passwd=password,
  20                               host=host, port=port, charset='utf8')
  21     else:
  22         cnx = MySQLdb.connect(db=path, user=user, passwd=password,
  23                               host=host, port=port, use_unicode=True)
  24         self._set_character_set(cnx, 'utf8')
  25 ...

MySQL Server

Versionswirrwarr 2

Zu allem übel ist es auch so, das nicht jede MySQLdb Version kompatibel zu allen MySQL Server Versionen sind. Die aktuelle MySQLdb v1.2.2 arbeitet mit MySQL v4.1 und v5.0 offiziell zusammen. Mit diesen beiden Server Verionen testen auch die Entwickler. Ältere MySQL Server Versionen bis hinunter zu v3.22.19 werden wahrscheinlich funktionieren.

Die jeweiligen Kombinationen von Modul und Server stehen in den Release Notes und können auf sourceforge eingesehen werden.

Datenbank Encoding

Eine neue Datenbank sollte so eingerichtet werden:

CREATE DATABASE DerDatenbankName DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

Links

Tags: Web | Db

MySQLdb troubleshooting (zuletzt geändert am 2012-09-14 18:40:19 durch anonym)