Dienstag, 22. Mai 2012


Artikel

Oktober 2006 | Artikel

Python, SQLObject und MySQL

(Link zum Artikel: http://www.entwickler.de/jaxenter//001087)

Kompetenz-Team

Text: von Thomas Kaufmann
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
Datenbanken sind das Herzstück vieler Online-Auftritte und auch Privatanwender nutzen dieselben für die verschiedensten Zwecke. Nichtsdestotrotz, die Arbeit mit einem RDBMS kann aufwändig sein. Für Python-Entwickler gibt es jetzt aber eine Erleichterung: SQLObject von Ian Bicking. Es handelt sich dabei um einen Mapper, d.h. aus Python-Objekten werden Datensätze generiert. Und: SQL brauchen Sie in diesem Fall auch nicht mehr zu schreiben, vielmehr regelt SQLObject diese Dinge.

SQLObject ist nach Aussage des Entwicklers Bicking ein "object-relational mapper". Was heißt das? Sie können, wie bereits erwähnt, mithilfe von Python-Objekten Datensätze abbilden und somit direkt Tabellen editieren. Der gesamte Vorgang geht vollkommen transparent über die Bühne, es wird lediglich eine Python-Klasse geschrieben. Schlussendlich bietet SQLObject bietet sogar die Möglichkeit, Datenbanken anzusprechen, die kein SQL verstehen. Apropos: Im Artikel wurde für sämtliche Beispiele MySQL verwendet. Arbeiten Sie hingegen mit einer anderen Datenbank, schauen Sie bitte in die Dokumentation.

Erste Schritte
SQLObject 0.6.1 (Die Beispiele hier wurden mit dieser Version erstellt. Mittlerweile ist SQLObject 0.7.1rc1 erschienen.) bietet Support für die Datenbanken MySQL, PostgreSQL (via psycopg), SQLite, Firebird, Sybase und MAX DB (auch als SAP DB bekannt). Es muss wenigstens Python 2.2 (oder höher) auf Ihrer Maschine laufen, da SQLObject regen Gebrauch von New-Style-Classes macht. Mit dem Aufruf python -V bringen Sie die Versionsnummer des Interpreters in Erfahrung. Außerdem benötigen Sie den Datenbanktreiber MySQLdb von Andy Dustman. Bei modernen Linux-Distributionen wie Debian, SuSE und Fedora gehört dieses Modul in der Regel zum Lieferumfang. Testen Sie, ob es installiert ist. Starten Sie den Python-Interpreter und geben Sie Folgendes ein:

  1. >>> import MySQLdb
  2. >>>

Erhalten Sie eine Fehlermeldung, müssen Sie das Modul über die Systemsteuerung des entsprechenden Systems nachinstallieren (beispielsweise unter SuSE mit YaST). Ebenfalls wichtig: Falls Python 2.2 an Bord ist, muss zusätzlich das mxDateTime-Package installiert werden. Anschließend besorgen Sie sich noch den SQLObject-Tarball aus dem Netz und entpacken das Archiv:

  1. ich@meinrechner:~> tar xvzf SQLObject-0.6.1.tar.gz

Danach wechseln Sie in das neu erstellte Verzeichnis und führen diesen Befehl aus:

  1. ich@meinrechner:~> python setup.py install

Möglicherweise werden für den Vorgang root-Rechte benötigt. Danach testen Sie mit

  1. >>> import sqlobject
  2. >>>

ob die Installation erfolgreich war. Erhalten Sie eine Fehlermeldung, überprüfen Sie, ob die oben genannten Komponenten vorhanden sind. Schauen Sie auch in die mitgelieferte Dokumentation. Last not least wird natürlich ein RDBMS (Relational Database Management System) benötigt. Testen Sie, ob MySQL läuft:

  1. ich@meinrechner:~> mysql -u root -p

Falls der Aufruf fehlschlägt, holen Sie die Installation von MySQL nach (gehört ebenfalls zum Lieferumfang aller modernen Linux-Distributionen).

Die Praxis
Das Akronym CRUD bringt die Arbeit mit Datenbanken auf den Punkt: Create, Read, Update und Delete. Hier ein einfaches Beispiel für den typischen Aufbau einer MySQL-Tabelle:

  1. CREATE DATABASE mitarbeiter;
  2. USE mitarbeiter;
  3. CREATE TABLE person (
  4. id INT PRIMARY KEY AUTO_INCREMENT,
  5. firstName VARCHAR(100) NOT NULL,
  6. ...
  7. ...
  8. lastName VARCHAR(100) NOT NULL
  9. );

Die Datenbank mitarbeiter, inklusive Tabelle person, könnte demnach mit dem nachstehenden Aufruf erzeugt werden; gesetzt den Fall, Sie speichern den Code als my_table.sql ab:

  1. ich@meinrechner:~> mysql -u root -p < my_table.sql

So weit, so gut. Wenn Sie SQLObject nutzen, können Sie sich diesen Schritt sparen. Sie müssen lediglich eine neue Datenbank anlegen:

  1. ich@meinrechner:~> mysql -u root -p
  2. Password: *******
  3. mysql> create database mitarbeiter;

Zum nächsten Schritt: Natürlich muss der Verbindungscode zum Server geschrieben werden. Dazu dient eine Python-Funktion (das Modul heißt Connection.py):

  1. #!/usr/bin/env python
  2. from sqlobject import *
  3. from sqlobject.mysql import builder
  4. def get_conn():
  5. conn = builder()(host='localhost', db='mitarbeiter', \
  6. user='ich', passwd='geheim')
  7. return conn

Zuletzt wird schließlich die Klasse erstellt, die den Datensatz aufnimmt (die Datei heißt tabelle.py):

  1. #!/usr/bin/env python
  2. from sqlobject import *
  3. from Connection import get_conn
  4. class Person(SQLObject):
  5. _connection = get_conn()
  6. firstName = StringCol(length=100)
  7. lastName = StringCol(length=100)
  8. Person.createTable(ifNotExists=True)

Dazu ein paar Worte. Die Klasse Person stellt mithilfe der importierten Funktion get_conn() eine Verbindung zum Server her. Über SQL müssen Sie an dieser Stelle nicht nachdenken, diese Aufgabe erledigt SQLObject. Die letzte Zeile

  1. Person.createTable(ifNotExists=True)

erstellt die Tabelle, aber nur, wenn sie nicht existiert (ifNotExists=True). Starten Sie das Programm:

  1. ich@meinrechner:~> python tabelle.py

Danach loggen Sie sich in MySQL ein und geben folgende Befehle ein, um das Ergebnis zu begutachten:

  1. mysql> use mitarbeiter;
  2. ...
  3. mysql> desc person;
  4. +------------+---------------+-----+----+---------+------------------+
  5. | Field | Type | Null | Key | Default | Extra |
  6. +------------+---------------+-----+-----+---------+------------------+
  7. | id | int(11) | | PRI | NULL | auto_increment|
  8. | last_name | varchar(100)| YES | | NULL | |
  9. | first_name | varchar(100)| YES | | NULL | |

Wie zu erkennen ist, legt SQLObject selbstständig ein ID-Feld an (obwohl die Variable kein Member der Klasse Person ist). Die übrigen Felder entsprechen den Member-Variablen der Klasse und werden intern in passende MySQL-Typen konvertiert; jede Klasse verfügt implizit über einen Satz von Feld-Typen (als Entsprechung zu MySQL-Typen). So stellt SQLObject beispielsweise für Zeichenketten StringCol (entspricht VARCHAR) bereit, für Wahrheitswerte BoolCol etc. (es gibt für jeden Feldtyp eine Klasse).

CRUD
Starten Sie erneut den Python-Interpreter und experimentieren Sie. Neue Datensätze werden auf diese Weise erzeugt (entspricht dem INSERT-Statement):

  1. >>> from tabelle import Person
  2. >>> per = Person(firstName='Heinz', lastName='Mustermann')
  3. >>> per
  4. <Person 10L lastName='Mustermann' firstName='Heinz'>
  5. >>> per1 = Person(firstName='Heidi', lastName='Musterfrau')
  6. >>> per1
  7. <Person 11L lastName='Musterfrau' firstName='Heidi'>

Tritt ein Fehler auf, generiert SQLObject automatisch eine Ausnahme. Schauen Sie erneut in die MySQL-Tabelle:

  1. mysql> SELECT * FROM person;
  2. ...
  3. | id | last_name | first_name |
  4. +----+--------------+------------ -+------------+
  5. | 10 | Mustermann | Heinz |
  6. | 11 | Musterfrau | Heidi |

SQLObject hat die Datensätze also sauber in die Tabelle geschrieben. So soll es sein. Ausgelesen werden Felder wiederum so:

  1. >>> per.firstName
  2. 'Heinz'
  3. >>> int(per.id)
  4. 10
  5. >>>

SQLObject verfügt auch über eine select-Methode. Innerhalb dieser Methode können Python-Konstrukte verwendet werden. Im Beispiel wird das Auftreten einer Zeichenkette in einer bestimmten Spalte (Feld firstName) gezählt:

  1. >>> Person.select(Person.q.firstName.startswith('Heid')). count()
  2. 1

Die Dokumentation liefert diesbezüglich weiterführende Informationen. Zum Schluss sehen Sie noch, wie einfach Datensätze verändert werden können (entspricht UPDATE):

  1. >>> per.firstName
  2. 'Heinz'
  3. >>> per.firstName = 'Rudi'
  4. >>> per.firstName
  5. 'Rudi'

Wenn Sie nun die Tabelle kontrollieren, sehen Sie umgehend die aktuellen Änderungen:

  1. mysql> SELECT * FROM person;
  2. ...
  3. | 10 | Mustermann | Rudi
  4. ...
Fazit
Der Artikel sollte einen Einblick in die Konzepte vermitteln. SQLObject läuft in der aktuellen Version stabil und vereinfacht die Arbeit des Datenbankentwicklers enorm: Die Schnittstelle ist elegant entworfen, die Lernkurve leicht zu bewältigen. Von Vorteil ist auch, dass SQLObject von Bicking aktiv weiterentwickelt wird. Außerdem gehört eine ausgezeichnete Dokumentation zum Lieferumfang, Sie sind also nicht auf sich selbst gestellt. Bicking plant des Weiteren, Support für Oracle zu integrieren und die Unterstützung für Transaktionen soll ebenfalls verbessert werden. In einer der nächsten Versionen wird auch ein Profiler enthalten sein, um den Entwickler beim Aufspüren von Performance-Engpässen zu unterstützen. Viel Erfolg.

Thomas Kaufmann

  1. http://www.python.org/

Kommentare