|
Mit Python via JDBC auf MySQL zugreifen!
Ein spannendes Thema, das leider zu wenig wahrgenommen wird und Praxisbeispiele sieht man eh selten. Das soll sich ändern. Ja, es ist wirklich kein Problem, Python-Klassen von Java-Klassen erben zu lassen und somit ist der Zugriff auf das mächtige Java Datenbank-API auch für Python-Entwickler leicht zu bewerkstelligen. Falls man das möchte;-).
Folgendes Szenario: Sie müssen/wollen/sollen aus einem Python-Script via JDBC auf eine Datenbank (in unserem Fall MysQL) zugreifen. Allerdings müssen ein paar Vorraussetzungen erfüllt sein, um das Ganze durchführen zu können. Die Programmiersprache Java muß installiert sein - möglichst die letzte stabile Version (derzeit j2sdk1.4.1). Ob das tatsächlich so ist, läßt sich mit dem Aufruf type java schnell in Erfahrung bringen. Die Ausgabe sollte so aussehen:
java is hashed (/home/merman/j2sdk1.4.1_01/bin/java)
Ist Java nicht installiert, müssen Sie es sich von der Sun-Website [1] besorgen oder auf eine Heft-CD (zum Beispiel aus dem Java-Magazin) bzw. eine Buch-CD zurückgreifen und es selbst installieren. Unter Linux wird die Sprache in der Regel bei einer Standard-Installation mit auf die Platte des Anwenders geschaufelt. Soweit so gut.
Um MySQL-basierte Programme mit Java schreiben zu können, benötigen Sie zusätzlich einen MySQL-spezifischen Treiber. Sehr beliebt und weit verbreitet ist Connector/J [2] - diesen Treiber hat auch der Autor benutzt. Besorgen Sie sich den passenden Treiber und folgen Sie der Installations-Anleitung.
Weiterhin benötigen Sie die aktuelle Jython-Version. Diese finden Sie wiederum unter [3]. Die letzte "stable version" trägt die Versionsnummer 2.1 - die Datei kann man kostenlos downloaden (ca. 2,1 MB groß).
Die Jython-Installation ist kinderleicht, folgen Sie einfach den Anweisungen im README (beziehungsweise der INSTALL-Datei). Aber was zum Teufel ist Jython eigentlich? Die Antwort lautet: Jython ist, im Gegensatz zu CPython (dem klassischen Python), einfach in Java implementiert worden, weiter nix. Doch, es ist langsamer;-). Somit stehen dem Python-Entwickler eigentlich zwei Sprachen zur Verfügung: Python und Java!
Ach ja, MySQL muß ebenfalls installiert sein - testen Sie das mit dem gleichen Aufruf, mit dem Sie nach Java gesucht haben. Das ist alles an Vorbereitungen.
Zur Praxis. Zuerst wird eine Java-Klasse geschrieben. Sie stellt die Verbindung zur Datenbank her. Diese Klasse enthält insgesamt nur zwei Methoden (eine Verbindungsmethode und eine Testmethode).
Anschließend muß noch eine Jython-Klasse implementiert werden. Diese Klasse erbt von der Java-Klasse, überschreibt die Testmethode der Superklasse und setzt schlußendlich die Anfrage an den Datenbank-Server ab. Fertig. Fangen wir mit Java-Klasse an.
import java.sql.*; import java.util.*;
public class MySQLClient { Connection conn = null;
// Standard-CTOR public MySQLClient () {} public Connection connect(String url, String user, String pwd) throws SQLException { try { Class.forName("com.mysql.jdbc.Driver").newInstance(); conn = DriverManager.getConnection(url, user, pwd); System.out.println("\nConnected!"); } catch (Exception ex) { ex.printStackTrace(); } return conn; }
public ArrayList dbCheck() throws SQLException { ArrayList dbData = new ArrayList(); // Verbindungsparameter durch eigene Angaben ersetzen: host, database, username, password conn = this.connect("jdbc:mysql://host/database", "username", "password"); DatabaseMetaData meta = conn.getMetaData(); System.out.print("\n ... PRODUCT: " + meta.getDatabaseProductName()); System.out.print("\n ... VERSION: " + meta.getDatabaseProductVersion()); System.out.print("\n ... DRIVER : " + meta.getDriverName()); System.out.print("\n ... DB-URL : " + meta.getURL()); System.out.print("\n ... USER : " + meta.getUserName()); System.out.println("\n"); dbData.add(meta.getDatabaseProductName()); dbData.add(meta.getDatabaseProductVersion()); dbData.add(meta.getDriverName()); dbData.add(meta.getURL()); dbData.add(meta.getUserName()); conn.close(); return dbData; } public static void main(String [] args) throws SQLException { MySQLClient mycli = new MySQLClient(); mycli.dbCheck(); } // end main } // end class
Die Klasse MySQLClient enthält zwei Methoden (connect() und dbCheck()); die erste Methode stellt lediglich die Verbindung zum Server her, die zweite Methode sendet die Anfrage an den Server und liefert im Erfolgsfall relevante Metadaten des Servers zurück. Mit diesem Kurz-Check ist der Anwender stets im Bilde, ob der Server läuft. Jetzt wird die Klasse kompiliert.
javac MySQLClient.java
Testen wir die Klasse:
java MySQLClient
In der Ausgabe sehen Sie wichtige Angaben, die der MySQL-Server auf die Standardausgabe gesendet hat. Es sollte soweit alles klar sein. Nun zur Python-Klasse. Achten Sie besonders auf die import-Anweisung im ersten try/except-Block. Hier wird nämlich die Java-Klasse importiert. Wichtig: die Java-Klasse muß vorher kompiliert worden sein, sonst wird eine Ausnahme geworfen. Die JDBC-Klasse überschreibt zudem die Methode dbCheck() - zusätzlich wird in diese Methode noch ein kurzer Gruß eingefügt. Das wars auch schon.
In __main__ wird eine Instanz von JDBC erzeugt und die überschriebene Methode wird aufgerufen. Diese wiederum delegiert intern den größten Teil der Arbeit an die Methode Super-Klasse; schließlich ist dort die Implementierung enthalten. Als Ergebnis sollten Sie die gleiche Ausgabe wie beim Aufruf der Java-Klasse zu Gesicht bekommen - mit einem Jython-Gruß.
#!/usr/bin/env jython
import sys
try: import MySQLClient as MYSQL except ImportError: print """ ImportError: Class not found.\n Usage:\n 1.) javac MySQLClient.java 2.) jython jdbc.py\n""" sys.exit(1) class JDBC(MYSQL): def __init__(self): pass # Delegation def dbCheck(self): try: print '\nGreetings from Jython:-)' mysql = MYSQL() mysql.dbCheck() except (Exception): print '\n*exception in JDBC -> dbCheck()*\n' print sys.exc_type, '\n', sys.exc_value, '\n\n*end exception*\n'
#... standalone ............................................................
if __name__ == '__main__':
try: db = JDBC() db.dbCheck() del db # delete instance except: print '\n*exception in __main__*\n' print sys.exc_type, '\n', sys.exc_value, '\n\n*end exception*\n'
Links:
[1] http://java.sun.com/ [2] http://www.mysql.com/downloads/ [3] http://www.jython.org/
Thomas Kaufmann
|