Entwicklung eines SQLite-Beispiels

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Montag 10. Juli 2006, 22:52

Hi!

Ich möchte ein kleines SQLite-Beispiel zusammenbasteln. Das Beispiel ist eine kleine Adressdatenbank, die über die Konsole bedient werden soll.

Das Hauptziel ist: Eine **schöne**, einfache Datenbankanwendung erstellen, die als Referenz für eine kleine SQLite-Anwendung dienen soll.

Was soll demonstriert werden?

- Verbindung zu SQLite-DB aufbauen
- Verbindung abbauen
- Zugriff auf Felder mit Feldnamen und mit Tupel-ID (Index)
- Erstellen von Tabellen
- Erstellen von CONSTRAINTS
- Erstellen von Indexen
- Erstellen von Abfragen mit mehreren Tabellen.
- CREATE TABLE
- CREATE INDEX
- SELECT
- INSERT
- UPDATE

Ich stelle den Quellcode vorerst mal hier rein, damit er von jedem benörgelt werden kann. Jeder Hinweis, wie etwas EINFACHER oder BESSER gemacht werden kann ist willkommen. :-)

ACHTUNG!!! Die Anwendung ist noch nicht fertig. Also bitte nicht bemängeln, dass man noch kein Menü für die Eingabe zur Verfügung hat.

Code: Alles auswählen

# DER CODE WURDE AUSGELAGERT
http://gelb.bcom.at/svn/pub/misc/sqlitebeispiele/einfache_adressenverwaltung/trunk/
http://gelb.bcom.at/trac/misc/wiki/SQLite-Beispiele/EinfacheAdressenverwaltung
Hier gehts ins Trac: http://gelb.bcom.at/trac/misc/wiki/SQLi ... verwaltung

Mit Bitte um deine Meinung,
Gerold
:-)
Zuletzt geändert von gerold am Dienstag 11. Juli 2006, 09:01, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. Juli 2006, 08:22

Hi @all!

Jens hat mich darauf hingewiesen, dass es nicht möglich war, in diesem Thread zu antworten.

Deshalb habe ich den Quellcode ausgelagert. Das Beispiel ist inzwischen schon in einem Subversion Repository. In der nächsten Arbeitspause werde ich mich darum kümmern, dass auch ein Trac dafür eingerichtet wird. Dann kann man den Code auch mit Codehighlighting betrachten.

Hier die Adresse des Beispiels im SVN-Repository:
http://gelb.bcom.at/svn/pub/misc/sqlite ... ung/trunk/

Wie im vorherigen Beitrag, bitte ich euch, dieses Beispiel so lange in der Luft zu zerreisen, bis ein vernünftiges Beispiel für Datenbankanfänger raus gekommen ist.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. Juli 2006, 08:35

Hi!

Das Beispiel ist jetzt in einem Trac.

http://gelb.bcom.at/trac/misc/browser/s ... dressdb.py

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. Juli 2006, 12:01

Hi!

Wie sich schmerzlich herausstellt, habe ich keine Erfahrung im Erstellen von Konsolenanwendungen. Meine letzte *echte* Konsolenanwendung habe ich noch mit dem "Commodore 128" programmiert. :oops:

Ich hoffe, es wird trotzdem brauchbar. Und -- ich bitte um Ratschläge. Auch während der Entwicklung.

http://gelb.bcom.at/trac/misc/browser/s ... tung/trunk

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 11. Juli 2006, 12:36

Und wieder ein neuer trac :P

Also was ich dir schreiben wollte... (War jetzt auch nicht so viel):

Ich würde hier: http://gelb.bcom.at/trac/misc/browser/s ... sdb.py#L48 nicht einfach except: pass machen, sondern wenigstens ein evtl. aufgetretenen Fehler ausgeben, auch wenn der User evtl. damit nix anfangen kann...
Ich mach in solchen Fällen meist sowas:

Code: Alles auswählen

except Exception, e:
    print "Ein Fehler ist bei ... aufgetreten:", e
Mit diesem hier ist das IMHO so eine Sache:

Code: Alles auswählen

39 	        # Abfrageergebnisse wie Dictionarys verwenden lassen.
40 	        # Diese Zeile muss **vor** dem Erstellen des Cursors stehen.
41 	        self.conn.row_factory = sqlite3.Row
Ich würde da vielleicht ehr ein DB unabhängige Sache nutzten, siehe auch [wiki]Dict Cursor[/wiki]
Wobei das in dieser kleinen Anwendung vielleicht auch etwas übertrieben ist. Aber es soll ja nur ein test sein, oder?

Generell würde mich interessieren, ob du nicht besser eine komplette Zwischenschicht zwischen DB und deiner Anwendung machen solltest... Vielleicht ist dabei SQLAlchemy interessant. Ist relativ klein und anscheinend fein :lol: Als Einstieg: http://www.sqlalchemy.org/docs/tutorial ... ingstarted

Ansonsten finde ich es interessant, das du öfters mit locals() arbeitest. Auf die Idee bin ich noch nie gekommen! Das vereinfach einige Sachen erheblich. Allerdings ist es IMHO ein wenig intransparenter...

Du hattest mit solchen zurück gelieferten Status ("ok_status") gearbeitet. Ist z.Z. auskommentiert... Würde man da nicht besser eine eigene exception definieren und damit arbeiten?

Was für so eine Beispielanwendug vielleicht sehr interessant ist, wäre ein kompletter unittest!

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. Juli 2006, 18:24

jens hat geschrieben:Und wieder ein neuer trac :P
Hi Jens!

Natürlich! :-) Diesmal aber mit einem besseren Namen, so dass ich mehrere, kleine Projekte dort unterbringen kann.

Was deine Vorschläge angeht: Vielen Dank! Ich werde mir zu jedem Punkt überlegen, wie ich es in der Demo unterbringen kann.

Einen Punkt werde ich allerdings unberücksichtigt lassen:
Ich mag Mapper wie "SQLAlchemy" nicht. Eigentlich gefallen mir **keine** dieser Zwischenschichten. Ich arbeite seit "Ewigkeiten" mit Datenbanken und will SQL einsetzen. Damit kann man so viel machen. -- Diese Zwischenschichten muss ich erst lernen und dann muss ich mich, anscheinend, auch noch mit weniger Macht über die Datenbank zufrieden geben.

Aber, wie schon gesagt. Die anderen Punkte nehme ich mir zu Herzen.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. Juli 2006, 18:39

jens hat geschrieben:nicht einfach except: pass machen, sondern wenigstens ein evtl. aufgetretenen Fehler ausgeben, auch wenn der User evtl. damit nix anfangen kann...
Ich mach in solchen Fällen meist sowas:

Code: Alles auswählen

except Exception, e:
    print "Ein Fehler ist bei ... aufgetreten:", e
Hi Jens!

Wenn ich das richtig verstanden habe, dann geht es um diese Methode:

Code: Alles auswählen

    #----------------------------------------------------------------------
    def __del__(self):
        """
        Alles schließen
        """
        
        try:
            self.cur.close()
        except:
            pass
        try:
            self.conn.close()
        except:
            pass
In diesem Fall kann doch niemand etwas dagegen tun oder irgendwie darauf reagieren, oder? Wenn ich das jetzt nicht falsch verstehe, dann wird die Verbindung zur Datenbank, früher oder später, sowiso vom Garbage C. getrennt. Mit einem close() in der Methode __del__(self) versuche ich das nur ein wenig sauberer hin zu bekommen.

Welcher Fehler könnte hier passieren, der den Benutzer interessieren könnte, ohne ihn zu verwirren? Das ist eine Überlegung, die ich mir öfter mal stelle, bevor ich dem Benutzer irgendwelche Meldungen zeige.

Wie wärs, wenn ich ein Logging einprogrammiere, welches den Fehler zwar protokolliert, dem Benutzer aber, der damit eh nichts anfangen kann, nichts davon sage?

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 11. Juli 2006, 21:06

Tja, ist halt die Frage für wen das Programm ist...

Aber selbst wenn es den User verwissen sollte, er weiß zumindest, das irgendwas nicht stimmt und könnte nachfragen ;)

Ansonsten sieht er einfach nix vom Fehler...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. Juli 2006, 21:29

jens hat geschrieben:er weiß zumindest, das irgendwas nicht stimmt und könnte nachfragen
Hi Jens!

Das ist es ja, das Problem. Wenn der Benutzer zu mir (dem Programmierer) kommt und mir sagt, dass hier ein Fehler auftaucht, dann würde ich ihm wohl sagen --> "Ignorier es". Was sollte ich an dieser Stelle des Programms noch tun? Ich warte, dass mir der GC die Datei wieder frei gibt oder dass der Computer neu gestartet wird. Spätestens dann ist die Datei wieder freigegeben.

Unter Windows 2000 kann ich manchmal einen leeren Ordner nicht löschen. >> er ist wirklich leer << Löschen kann ich ihn erst dann, wenn ich mich vom Windows ausgeloggt und wieder eingeloggt habe. Genau diese Fälle sind es, die öfter auftauchen und weshalb ich Fehler bei nicht ganz so wichtigen Aufräumarbeiten gerne ignorieren würde.

Um von diesen Fehlern doch irgendwann etwas mit zu bekommen und die Dringlichkeit einstufen zu können -- dafür könnte vielleicht doch eine Logdatei reichen.

Das sind sie -- meine Überlegungen zu diesem Thema. Jetzt würde mich noch interessieren, wie andere darüber denken.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 11. Juli 2006, 21:31

gerold hat geschrieben:Unter Windows 2000 kann ich manchmal einen leeren Ordner nicht löschen. >> er ist wirklich leer << Löschen kann ich ihn erst dann, wenn ich mich vom Windows ausgeloggt und wieder eingeloggt habe.
Dann solltest du mal mit sysinternal's ProcessExplorer nachsehen, ob ein "offenes Handle" da ist ;)

Aber im Fall vom DB "schließen"... Sollte das nicht immer funktionieren? Im Normalfall?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. Juli 2006, 21:35

jens hat geschrieben:Dann solltest du mal mit sysinternal's ProcessExplorer nachsehen, ob ein "offenes Handle" da ist ;)
Hi Jens!

Guter Tipp! Werde ich mir sicher ansehen.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. Juli 2006, 21:37

jens hat geschrieben:Aber im Fall vom DB "schließen"... Sollte das nicht immer funktionieren? Im Normalfall?
Hi Jens!

Gute Frage! Ich werde mal darüber schlafen.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten