Seite 4 von 4
Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 00:02
von snafu
Den Teil mit der Erzeugung der URL kannst du übrigens einfacher haben, wenn du die übergebenen Argumente ohnehin als Instanzattribute bindest:
Code: Alles auswählen
class DatabaseConnection(object):
def __init__(self, dbms, dbdriver, dbuser, dbuser_pwd, db_server_host, dbport, db_name):
self.dbms = dbms
self.dbdriver = dbdriver
self.dbuser = dbuser
self.dbuser_pwd = dbuser_pwd
self.db_server_host = db_server_host
self.dbport = dbport
self.db_name = db_name
self.url = '{.dbms}+{.dbdriver}://{.dbuser}:{.dbuser_pwd}@{.db_server_host}:{.dbport}/{.db_name}'.format(self)
Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 00:10
von Sophus
@snafu: In meinem konkreten Beispiel wird ja die Verbindung in der DatebaseConnection()-Klasse eingerichtet. Herrgestellt wird ja erst eine Verbindung, wenn eine Abfrage abgesetzt wird, da das Session()-Objekt et dann die Verbindung aufbaut. Wie dem auch sei. Auf meiner View-Seite (auch GUI genannt) kann ich schlecht eine Exception abfangen. Denn die DatebaseConnection()-Klasse wirft ja keine Fehlermeldung bei falscher Eingabe zurück.
Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 00:28
von snafu
Sophus hat geschrieben:Denn die DatebaseConnection()-Klasse wirft ja keine Fehlermeldung bei falscher Eingabe zurück.
In `__init__()` fängst du doch selber den möglicherweise auftretenden `SQLAlchemyError` ab. Wenn du dieses Abfangen weglässt, dann wird der Fehler automatisch hochgereicht und die Klasseninstanz wird infolgedessen nicht erzeugt. Das macht ja IMHO auch Sinn, weil mit einer `DatabaseConnection()`-Instanz, die keine erfolgreiche Verbindung herstellen konnte, wohl wenig anzufangen ist. Man würde den Anwender dann über die GUI bitten, die Angaben zu korrigieren und eine Istanziierung der `DatabaseConnection()` mit den korrigierten Angaben vornehmen.
Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 00:52
von Sophus
@snafu: Manchmal brauche ich eine Weile, bis ich etwas verstehe. Ich habe es eben einfach mal ausprobiert und dir vertraut. Ich habe mit Absicht falsche LogIn-Daten eingegeben und tatsächlich. Ich konnte auf der Seite der GUI die Fehler abfangen. Danke dir.
Da ich allerdings auf der GUI-Seite kein SQLAlchemy importieren möchte, habe ich meine Try/Exeption wie folgt konstruiert:
Code: Alles auswählen
def db_login_access_data(self, dbm_system, dbm_driver, db_user,
db_passwd, db_host, db_port, db_name):
try:
self.db_connection = DatabaseConnection(dbm_system, dbm_driver, db_user,
db_passwd, db_host, db_port, db_name)
return True
except Exception as Err:
print "MyEX", Err
return Err[0]
Ich weiß, dass Exception eine Art Basis-Klasse ist, um alle Exceptions abzufangen. Sollte man nicht machen. Denn genauso gut könnte ich auch eine nackte Exception benutzen. Da ich aber nicht explizit
SQLAlchemyError abfangen kann, erschien mir das als mögliche Lösung?
Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 01:04
von jerch
@Sophus:
Dieses Stochern hilft doch nicht weiter. Bitte lies Dir die Grundlagen an - was Exceptions sind, wie sie sich verhalten und was hieraus die Implikationen für den korrekten Umgang damit sind.
Sophus hat geschrieben:Da ich allerdings auf der GUI-Seite kein SQLAlchemy importieren möchte, habe ich meine Try/Exeption wie folgt konstruiert:
Ja und warum möchtest Du das dort nicht importieren? Hast Du Angst, das der Namensraum "dreckig" wird? Ich frage das, weil sowas bei Dir schon öfter durchklang. Auch müsstest Du hierfür nicht alles von Sqlalchemy importierten sondern nur den Exceptiontypen, welchen Du dort SINNVOLL behandeln kannst. ALLES ANDERE BLEIBT UNBEHANDELT. Deine Dummy-print-Exception-Behandlungen machen Dir das Leben nicht leichter sondern schwerer.
Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 01:11
von Sophus
@jerch: Das Wort "dreckig" trifft es gut. Ich hatte gehofft, dass ich den Namensraum nicht zukleistern muss. Aber gut, dann setze ich noch einen weiteren Kandidaten in den Namensraum. Danke dir.
Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 01:13
von snafu
Jetzt verlagerst du das Abfangen der Exception, ohne etwas sinnvolles damit zu tun, an eine andere Stelle im Code.
Worin besteht für dich das Problem, die Exception erst dort abzufangen, wo du sie in der GUI als Fenster mit Fehlermeldung ausgeben kannst?
Mal ganz direkt gesagt: Das Konstrukt ``except SomeError as err: return err[0]`` ist fast immer eine schlechte Idee. Falls es dir darum geht, den Code zum Erstellen der Fehlermeldung in der GUI auslagern willst, dann reiche besser das komplette Exception-Objekt weiter:
Code: Alles auswählen
try:
# was auch immer
except SomeError as error:
show_error_message(error)
# alternativ: Übergabe der Meldung als String
show_error_message(str(error))
Der Punkt ist, die Rückgabe irgendwelcher Fehlerwerte zu vermeiden. Das ist in Sprachen mit eingebauten Exceptions einfach unschön.
Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 01:34
von jerch
Sophus hat geschrieben:Ich hatte gehofft, dass ich den Namensraum nicht zukleistern muss.
Die Sorge dürfte unbegründet sein, ein Namesraum hat nicht nur 4 Wände wo jeweils nur ein Wort draufpasst

Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 01:36
von Sophus
@↓snafu: Besten dank für den Hinweis. Ich habe deinen Rat gefolgt:
Code: Alles auswählen
def create_generally_msg(self, err_msg):
from xarphus.core.manage_qt import custom_message_box
mBox = custom_message_box(self, err_msg[0], self.tr('Fehler'), QMessageBox.Critical)
setIc_OK = QIcon(self.check_icon)
mBox.addButton(
QPushButton(setIc_OK, self.tr(" Ok")),
mBox.AcceptRole) # An "OK" button defined with the AcceptRole
mBox.exec_() # QDialog.exec_ is the way that it blocks window
# execution and allows a developer to wait for user
# input before continuing.
def db_login_access_data(self, dbm_system, dbm_driver, db_user,
db_passwd, db_host, db_port, db_name):
try:
self.db_connection = DatabaseConnection(dbm_system, dbm_driver, db_user,
db_passwd, db_host, db_port, db_name)
return True
except SQLAlchemyError as Err:
self.create_generally_msg(str(Err))
Anmerkung: Ich kreiere mir meine eigene Messagebox, mit eigenen Buttons etc. Ich habe das Import mit Absicht in die Funktion gepackt, damit es für euch nachvollziehbarer ist, woher
custom_message_box() stammt.
Und aussehen tut das so:

Re: SQLAlchemy: Session richtig verstehen
Verfasst: Donnerstag 11. Februar 2016, 02:15
von snafu
Streng genommen ist die Rückgabe von `True` auch wieder unnötig. Warum nimmst du nicht einfach eine Endlosschleife, die solange nach den Benutzereingaben fragt bis erfolgreich eine `DatabaseConnection` erzeugt und zurückgegeben werden konnte?
Falls der Anwender dabei auch auf "Abbrechen" drücken darf, dann wäre das ja auch über eine Art ``while not cancelled:`` möglich.
EDIT: Wobei das wohl eine Stilfrage ist, ob man eine Endlosschleife mit Abbruchmöglichkeit baut, oder ob man quasi schon nach dem ersten Mal aufgibt und dem Anwender die freie Entscheidung überlässt, ob er es erneut versuchen möchte. Jedenfalls finde ich die Rückgabe eines sinnvollen Objektes als Resultat besser als ein bloßes `True`. Denn um zu signalisieren, dass etwas *nicht* funktioniert hat, nutzt man - wie schon zigmal geschrieben - in Python üblicherweise Exceptions anstelle von Wahrheitswerten.