Mehrfaches includen einer Datenbankklasse

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
zoe
User
Beiträge: 8
Registriert: Donnerstag 29. März 2007, 10:28

Hi !

Ich habe 3 Python files nennen wir sie a.py, b.py und db.py

db.py ist eine einfache wrapper klasse für den Zugriff auf MySQL. b.py included db.py um mittels einer Instanz der Klasse Datenbankoperationen durchzuführen. Selbiges macht auch a.py aber a.py included zusätzlich noch b.py um einige Funktionen daraus zu nutzen.
Wenn ich aber b.py in a.py include habe ich dort schon mal zwei Instanzen von der db Klasse obwohl eine reichen würde.

Hoffe es ist einigermaßen klar was ich meine. Nun zu meinem Problem: Irgendwie scheint mir das nicht sonderlich elegant. Wie würde man einen zentralen Zugriffspunkt auf die db sauber implementieren ?

Danke!
BlackJack

Entweder ohne Klasse, oder mit einer Factory-Funktion, die bei den gleichen Verbindungsdaten auch das selbe Objekt zurückgibt. Je nachdem wie komplex es werden soll, oder wie einfach es bleiben darf.

Die einfachste Variante wäre es, das Modul als "Singleton" zu benutzen.
zoe
User
Beiträge: 8
Registriert: Donnerstag 29. März 2007, 10:28

Ok ich glaub ich muss noch etwas über Softwaretechnik lesen um Möglichkeit 2 umzusetzen :) Aber Wenn ich keine Klasse verwenden würde, hätte ich die Möglichkeit entweder bei jedem Datenbankaufruf eine neue Verbindung zu öffnen und wieder zu schließen (sehr langsam bei vielen Aufrufen vermute ich mal) oder ich öffne die Verbindung einmal am Anfang und stelle diese global zu Verfügung. Aber dann habe ich wieder das Problem beim includen von b.py in a.py (die ja beide eine globale db Verbindung bereitstellen) oder ?
BlackJack

Ich weiss nicht ob ich das Problem richtig verstehe: Wenn Du `db` sowohl in `a` als auch in `b` importierst, dann gibt es nur *ein* `db`-Modul-Objekt und nicht zwei. Wenn Du also in `db` *eine* Datenbankverbindung verwaltest, gibt es auch nur eine im ganzen Programm.

Wirklich minimal liesse sich das so lösen:

Code: Alles auswählen

import db       # Das "echte" Datenbankmodul.


connection = None


def connect(params):
    global connection
    connection = db.connect(params)
    return connection


def final_close():
    connection.close()
zoe
User
Beiträge: 8
Registriert: Donnerstag 29. März 2007, 10:28

Hmm...

Ich versuchs nochmal genauer zu erklären:

db.py

Code: Alles auswählen

import MySQLdb 
class mSQL:
 def __init__(self, host, user, passwd, db):
 def connect(self):
 def getQuery(self, query):
 def disconnect(self):
b.py

Code: Alles auswählen

import db.py

db = mSQL.mSQL(host,user,passw,name)

db.connect()

def g:
...


db.disconnect()



a.py

Code: Alles auswählen

import db.py
import b.py

db = mSQL.mSQL(host,user,passw,name)

db.connect()

def f1:
...

f1()
b.g()

db.disconnect()




die Funktion g() (und weitere) in b.py nutzt jetzt das globale db Objekt in b.py
In a.py gibt es Funktionen (wie f1() ) die eine db Verbindung brauchen daher auch hier ein db Objekt. Es werden aber weiterhin Funktionen aus dem includierten b.py aufgerufen. In dem Moment wo ich aber b.py in a.py includiere habe ich doch 2 Objekte (auch noch gleichen namens) ?

Das Problem ist eben, dass ich in beiden files ein db Objekt brauche (denn beide files sollen auch unabhängig vom anderen lauffähig sein) aber ich Probleme bekomme wenn ich die eine in die andere Datei includiere.

Ich hoffe es ist so klarer was mein Problem ist - sorry falls die bisherigen Lösingsansätze schon auf dieses Problem passen - dann habe ich das noch nicht verstanden...

Danke!
BlackJack

Ich glaube Du verstehst ``import`` falsch. Das schaut nach, ob das Modul schon geladen wurde, falls ja wird einfach das schon geladene Modulobjekt an den entsprechenden Namen im importierenden Modul gebunden, ansonsten wird es einmal geladen und der Code auf Modulebene wird ausgeführt.

``import`` ist kein ``#include`` wie in C, das den Quelltext des anderen Moduls an der Stelle einsetzt wo es steht. Bei Deinen Beispielen gehe ich mal davon aus, dass Du nicht ``mSQL.mSQL(…)`` sondern ``db.mSQL(…)`` in den Modulen `a` und `b` meinst. Du hast nach dem Ablauf von `a` zwei Datenbank-Objekte, eines das in `a` über den Namen `db` erreichbar ist, und ein anderes das `b.db` heisst.
Antworten