Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Python-de] "Export" an Modul möglich?

1 view
Skip to first unread message

Ulrich Goebel

unread,
Jul 10, 2023, 6:03:32 PM7/10/23
to
Guten Abend,

in einer Datenbank-Anwendung, die später SQLite, PostgreSQL und evt.
weitere Enginges bedienen soll, habe ich folgende Situation:

Modell.py definiert mir Objekte, die auf einer SQL-DB operieren. Dieses
Modul möchte ich auch für andere DB-Anwendungen nutzen können. Daher
kennt Modell.py die tatsächliche DB nicht.

Modelle.py definiert anwendungsspezifisch Objekte, die die jeweilige
SQL-Tabellenstruktur abbilden. Grundlage dafür sind die (generischen)
Objekte aus Modell.py

Tools.py definiert weitere anwendungsspezifische Operationen auf der DB,
typischerweise SELECT Anwendungen für Auswertungen.

Main.py ist das Hauptprogramm. Das Hauptprogramm bekommt vom Benutzer
z.B. auch Benutzernamen und Passwort für den DB-Zugang.


Mein Problem: Wie bekommen Modell.py und Tools.py einen gültigen
DB-Konnektor? Möglichst sogar den selben?


Folgenden Versuch habe ich gemacht:

In Modell.py gibt es eine
Klasse DB_Konnektor mit einem Zustand DB_Konnektor.DB und einer Methode
DB_Konnektor.Init(Zugangsdaten); letztere erzeugt den DB_Konnektor und
speichert ihn in dem Klassenzustand DB_Konnektor.DB
Außerdem gibt es in Modell.py die
Funktion DB(), die einfach den Zustand DB_Konnektor.DB zurück gibt.

In Main.py, Modelle.py und Tools.py kann ich nun aus Modell.py den
DB_Konnektor und die Funktion DB() importieren. Und tatsächlich scheint
der DB_Konnektor nach Aufruf von DB_Konnektor.Init(Zugangsdaten)
sichtbar zu sein.

Den Code der Python-Files habe ich unten wiedergegeben.

Ist das ein gutes, "pythonisches" Vorgehen? Oder gibt es eine elegantere
Möglichkeit?

Unschön bleibt aus meiner Sicht, dass der DB-Konnektor nur über eine
Funktion zugänglich ist, also DB(). Schöner wäre DB, also eine "Zustand
des Moduls" - aber das gibt es wohl nicht? So sieht die Syntax später
z.B. so aus:
Cur = DB().cursor()
DB().commit()
Schöner wäre:
Cur = DB.Cursor()
DB.commit()

Wäre es naheliegend, die Klasse DB_Konnektor von den Konnektor-Klassen
der implementierten Schnittstellen erben zu lassen? Also etwa:

class DB_Konnektor(sqlite3.Connector, psycopg2.extensions.connection)
def __init__(Typ, ...):
if Typ == 'SQLite':
sqlite3.Connector.__init__(...)
elif Typ == 'PostgreSQL':
psycopg2.extensions.connection.__init__(...)
...

Vielen Dank für Hilfe oder Hinweise!
Gruß Ulrich


Hier mein vorläufiger Code:

====== Modell.py ======
class DB_Konnektor():
DB = "DB Prototyp (unbrauchbar)"

def Init(DB_Name):
DB_Konnektor.DB = DB_Name

def DB():
return DB_Konnektor.DB

class Modell():
def DB(self):
print('Aus Sicht von Modell.Modell ist DB: {}'.format(DB()))
return DB_Konnektor.DB

### Die Klasse Modell ist in Wirklichkeit sehr umfangreich.
### Sie greift auf den DB-Konnektor zurück.
###
### Hier folgen weitere Objekte, die auch auf den DB-Konnektor
### zurückgreifen.


====== Modelle.py ======
from Modell import *

### Hier folgen die Klassen, die Datenbank-Tabellen abbilden.
### Grundlage dafür sind die in Test_Modell
### definierten Objekte.


====== Tools.py ======
from Modelle import *

def Tools():
print('Aus Sicht von Tools ist DB: {}'.format(DB()))

### Hier folgen eine Reihe von Objekten, die auf den
### DB-Konnektor zurückgreifen.


=== Main.py ===
from Modell import DB
from Modelle import *
from Tools import *

M = Modell()

### Vor dem Aufruf von DB_Konnektor.Init() sieht es so aus:
print('Aus Sicht des Hauptprogramms vor Init ist DB: {}'.format(DB()))
print('Aus Sicht des Hauptprogramms vor Init ist M.DB: {}'.format(M.DB()))
Tools()

### Aufruf von DB_Konnektor.Init(Zugangsdaten):
DB_Konnektor.Init("DB brauchbar.")

### Nach dem Aufruf von DB_Konnektor.Init(Zugangsdaten)
### sieht es so aus:
print('Aus Sicht des Hauptprogramms nach Init ist DB: {}'.format(DB()))
print('Aus Sicht des Hauptprogramms nach Init ist M.DB: {}'.format(M.DB()))
Tools()



--
Ulrich Goebel
Hainallee 40, 44139 Dortmund

joc...@wersdoerfer.de

unread,
Jul 11, 2023, 2:10:30 AM7/11/23
to


> Am 10.07.2023 um 23:45 schrieb Ulrich Goebel <m...@fam-goebel.de>:
>
> Ist das ein gutes, "pythonisches" Vorgehen? Oder gibt es eine elegantere Möglichkeit?

Hmm, kennst du das Repository-Pattern schon? Das ist so der übliche Weg, wenn man
die Datenhaltung wegabstrahieren möchte:

https://www.cosmicpython.com/book/chapter_02_repository.html

> Unschön bleibt aus meiner Sicht, dass der DB-Konnektor nur über eine Funktion zugänglich ist, also DB(). Schöner wäre DB, also eine "Zustand des Moduls" - aber das gibt es wohl nicht? So

Klar, das geht auch. Aber Attribute von Modulen sind halt für alle gleich, d.h. wenn man das
ändern sollte, ändert man es für alle, die es benutzen.

Viele Grüße
Jochen

c.b...@posteo.jp

unread,
Jul 11, 2023, 3:29:12 AM7/11/23
to
Hallo Ulrich,

ich kenne deinen Anwendungsfall nicht, aber möchte eine Sache zu
bedenken geben, die ich aus meinen Anfangszeiten mitgenommen habe.

Datenbank sind ziemlich cool und so. Auf den ersten Blick erscheinen sie
meist als das Mittel der Wahl. Sie an eine Anwendung anzubinden ist aber
häufig sehr aufwendig und noch aufwendiger diese Anbindung zu warten.

Manchmal ist es sinnvoller vielleicht doch auf eine Datenhaltung ohne
Datenbank zurückzugreifen; Textdateien, JSON, CSV, Pickle-Files. Ein
bisschen Verwaltungs-Logik muss man dann selbst implementieren, aber
langfristig spart es viel Arbeit, weil man die ganze "Last"
(Abstraktionsschichten, Code-Wartung, Unittests, ...) die man sich mit
einer Datenbank dazu holt wegfällt.

Es ist eine Kosten-Nutzen-Rechnung.

Schöne Grüße
Christian

Peter J. Holzer

unread,
Jul 11, 2023, 6:59:24 AM7/11/23
to
On 2023-07-10 21:45, Ulrich Goebel <m...@fam-goebel.de> wrote:
> Unschön bleibt aus meiner Sicht, dass der DB-Konnektor nur über eine
> Funktion zugänglich ist, also DB(). Schöner wäre DB, also eine "Zustand
> des Moduls" - aber das gibt es wohl nicht? So sieht die Syntax später
> z.B. so aus:
> Cur = DB().cursor()
> DB().commit()
> Schöner wäre:
> Cur = DB.Cursor()

Also einen Methodennamen, der mit einem Großbuchstaben beginnt, finde
ich nicht schöner, sondern ziemlich irritierend.

> DB.commit()

Oh, Du meinst das?

Geht natürlich genauso. Die Variable musst Du dann halt vorher
initialisieren und das Behandeln von Verbindungsabbrüchen wird auch
komplizierter. Aber wenn Du den Cursor schon hast, hast Du auch
eine Verbindung zur Connection:

Cur.connection.commit()

(Und "cur" würde ich auch mit kleinem c schreiben)

hp
0 new messages