2017-03-24 1 views
3

Ich benutze Python 2 mit psycopg2 v2.6.2. Ich bin eine Reihe von psycopg2 Befehle ausgeführt wird, und alle Fehler zu kontrollieren:Fehlerbehandlung in psycopg2 - ein Fehler scheint mehr zu erzeugen?

for r in records: 
    county = r[0] 
    q = 'INSERT INTO allparcels(county, geom) ' 
    q += "SELECT %s, ST_Union(ST_Buffer(wkb_geometry, 0)) FROM parcel " 
    q += "WHERE county=%s" 
    print q % (county, county) 
    try: 
    cursor.execute(q, (county, county)) 
    conn.commit() 
    except Exception, e: 
    print e 
    print e.pgerror 
cursor.close() 
conn.close() 

Diese Datensätze für die ersten paar läuft, dann ich ERROR: current transaction is aborted, commands ignored until end of transaction block in schneller Folge für den ganzen Rest der Reihen erhalten.

Seltsamerweise, wenn ich einen der späteren Befehle nehme und es direkt in meiner Datenbank laufe, funktioniert es gut. Ich denke, die späteren Fehler haben etwas mit psycopg2 und meiner Fehlerbehandlung zu tun, nicht mit dem SQL-Befehl.

Ich denke, ich muss den Fehler nicht korrekt behandeln. Ich möchte, dass mein Skript den Fehler druckt, und fahre dann glatt mit dem nächsten Befehl fort.

Wie soll ich das stattdessen tun?

Antwort

4

Das Problem hier ist die folgende:

try: 
    # it is this specific line that causes an error 
    cursor.execute(q, (county, county)) 

    # this never happens, so the transaction is still open 
    conn.commit() 
except Exception, e: 
    ... 
    # you never issued a rollback on the transaction ... its still open 

Wie Sie sehen können, wenn cursor.execute Sie scheitert dann weder versuchen, die Transaktion zu begehen oder es wieder rollen. Bei den nächsten Iterationen durch die Schleife wird versucht, SQL für eine bereits abgebrochene, aber nicht zurückgenommene Transaktion auszuführen.

Stattdessen müssen Sie diese Art von Muster Antwort

try: 
    cursor.execute(...) 
except Exception, e: 
    conn.rollback() 
else: 
    conn.commit() 
+0

Ehrfürchtig - vielen Dank! – Richard

0

donkopotamus' folgen, ist ziemlich gut. Es hat ein Problem, dass es die gesamte Transaktion zurücksetzt, was definitiv unerwünschtes Verhalten sein könnte, wenn Sie diese Abfrage als Teil eines größeren Transaktionsblocks ausführen. Falls diese Abfrage Teil eines größeren Transaktionsblocks ist, sollten Sie die Verwendung von Savepoints in Betracht ziehen:

try: 
    cursor.execute("savepoint my_save_point") 
    cursor.execute(query) 
except: 
    cursor.execute("rollback to savepoint my_save_point") 
finally: 
    cursor.execute("release savepoint my_save_point") 
Verwandte Themen