2016-10-22 1 views
1

Ich habe ein Datenbankschema, das in einer Vielzahl von verschiedenen Datenbank-Engines implementiert werden könnte (sagen wir eine MS Access-Datenbank, die ich mit pyodbc oder einer SQLite-Datenbank verbinden werde Eingebautes sqlite3-Modul als einfaches Beispiel).Catch Python DatabaseErrors generisch

Ich möchte eine Fabrik Funktion/Methode erstellen, die eine Datenbankverbindung des entsprechenden Typs auf einige Parameter, ähnlich der folgenden Basis zurückgibt:

def createConnection(connType, params): 
    if connType == 'sqlite': 
     return sqlite3.connect(params['filename']) 
    elif connType == 'msaccess': 
     return pyodbc.connect('DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ={};'.format(params['filename'])) 
    else: 
     # do something else 

Jetzt habe ich eine Abfrage-Code Kapiert sollte mit jedem Verbindungstyp arbeiten (da das Schema unabhängig von dem zugrunde liegenden DB Motor identisch ist), aber eine Ausnahme auslösen kann, die ich zu fangen brauchen werden: ich habe

db = createDatabase(params['dbType'], params) 

cursor = db.cursor() 

try: 
    cursor.execute('SELECT A, B, C FROM TABLE') 
    for row in cursor: 
     print('{},{},{}'.format(row.A, row.B, row.C)) 

except DatabaseError as err: 
    # Do something... 

das Problem ist, dass die Klassen Database von jeder DB API 2.0-Implementierung nicht shar e eine gemeinsame Basisklasse (außer der allzu generischen Ausnahme), weshalb ich nicht weiß, wie man diese Ausnahmen generisch abfängt. Offensichtlich konnte ich etwas tun, wie folgt aus:

try: 
    # as before 
except sqlite3.DatabaseError as err: 
    # do something 
except pyodbc.DatabaseError as err: 
    # do something again 

... wo ich einen expliziten catch-Block für jede mögliche Datenbank-Engine enthalten. Aber das scheint mir nicht pythisch zu sein.

Wie kann ich DatabaseErrors von verschiedenen zugrunde liegenden DB API 2.0-Datenbankimplementierungen generisch abfangen?

Antwort

1

Es gibt eine Reihe von Ansätzen ist:

  1. Verwenden Sie eine allumfassende Ausnahme und dann herausfinden, was Ausnahme ist. Wenn es nicht in Ihrer Liste ist, erhöhen Sie die Ausnahme erneut (oder Ihre eigene). Siehe: Python When I catch an exception, how do I get the type, file, and line number?

  2. Vielleicht möchten Sie das Problem auf eine andere Art und Weise lösen: Ihr Werkscode sollte auch die Ausnahme zum Testen bereitstellen.

  3. Ein einfacher Ansatz aus meiner Sicht (und der, den ich in der Praxis verwende) ist, eine Klasse für alle Datenbankverbindungen zu haben und sie für jeden spezifischen Datenbanktyp/Syntax abzuleiten. Vererbung ermöglicht Ihnen, alle Besonderheiten zu berücksichtigen. Aus irgendeinem Grund musste ich mich nie um dieses Problem kümmern.

+0

Ihre Lösung # 2 hat den Trick gemacht. Es war mir nicht eingefallen, dass außer Aussagen dynamisch waren. Also gebe ich jetzt die verbindungs- und verbindungsspezifische Ausnahmeklasse von der Factory-Funktion zurück und teste den zurückgegebenen Ausnahmetyp in der except-Anweisung. Klappt wunderbar! –