wake-up-neo.com

DictCursor scheint unter psycopg2 nicht zu funktionieren

Ich habe vorher noch nicht mit psycopg2 gearbeitet, aber ich versuche, die Cursorfabrik in DictCursor zu ändern, sodass fetchall oder fetchone anstelle einer Liste ein Wörterbuch zurückgibt.

Ich habe ein Testskript erstellt, um die Dinge zu vereinfachen und nur diese Funktionalität zu testen. Hier ist mein kleiner Code, der meiner Meinung nach funktionieren sollte

import psycopg2
import psycopg2.extras

conn = psycopg2.connect("dbname=%s user=%s password=%s" % (DATABASE, USERNAME, PASSWORD))

cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
cur.execute("SELECT * from review")

res = cur.fetchall()

print type(res)
print res

Die res-Variable ist immer eine Liste und kein Wörterbuch, wie ich es erwarten würde.

Eine aktuelle Problemumgehung, die ich implementiert habe, besteht darin, diese Funktion zu verwenden, die ein Wörterbuch erstellt, und jede Zeile auszuführen, die von fetchall zurückgegeben wird.

def build_dict(cursor, row):
    x = {}
    for key,col in enumerate(cursor.description):
        x[col[0]] = row[key]
    return d

Python ist Version 2.6.7 und Psycopg2 ist Version 2.4.2.

47
Jim
res = cur.fetchall()

macht res eine Liste von psycopg2.extras.DictRows. 


Anstatt cur.fetchall aufzurufen, können Sie alternativ die Tatsache nutzen, dass cur eine Iteration ist:

cur.execute("SELECT * from review")
for row in cur:
    print(row['column_name'])

und somit können Sie mit dict- artiger Syntax auf die Daten zugreifen.

26
unutbu

Verwenden Sie RealDictCursor: 

cur = conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor)
cur.execute("SELECT * from review")
res = cur.fetchall()    

Dadurch erhalten Sie eine Liste mit Zeilen als echte Python-Wörterbücher anstelle von "Erweiterte Psycopg2-Liste".

85
kerma

Eine andere Lösung wäre die Verwendung des benannten Tupel-Cursors , da der Real Dict-Cursor jede Abfrage unterbricht, die Ganzzahl-Indikatoren verwendet, wie in der Dokumentation beschrieben.

Mit Named Tuple Cursors können Sie wie folgt auf die Punktsyntax zugreifen:

import psycopg2
import psycopg2.extras
cur = conn.cursor(cursor_factory = psycopg2.extras.NamedTupleCursor)
cur.execute("SELECT * from review")
res = cur.fetchone()
res.key1
res.key2

Das hält die Dinge aufgeräumt und bricht nichts, soweit ich weiß.

6
Brideau

Obwohl dies eine ältere Frage ist, kommt sie immer noch in google auf, also dachte ich, ich würde meinen Code für alle anderen hinzufügen, die vom großen G kommen.

Für mich habe ich mehrere Zeilen, die ich gerne in ein Wörterbuch zurückbringen möchte. Idealerweise möchte ich keine Schleife oder ähnliches verwenden, um den Schlüssel aus einem Feld in der Datenbank zu setzen. 

Mit dict comprehension syntax kann ich also folgendes tun.

Tabellenzeilen ins Wörterbuch


pgCursor = Conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor)
pgCursor.execute("SELECT * FROM tablename;",([]))
dictRows = {n['id']: n for n in pgCursor}

Funktion & Aufruf

#NOTE this is using a class object hence the self param
def DBTableToDictByID(self, squery):
    self.Pointer.execute(squery,([]))
    return {n['id']: n for n in self.Pointer}

dictRows = self.DBTableToDictByID("SELECT * FROM tablename;")

Während dies eine for x in y -Schleife verwendet, ist Pythonic soweit ich das beurteilen kann ... Hoffentlich wird dies einigen da draußen helfen.

3
Mayhem

Zusätzlich zur Verwendung der RealDictCursor-Funktion müssen Sie möglicherweise auch nach allen Spalten (Mit dem Symbol * nach dem Auswählen) fragen, wie in der Antwort beschrieben.

Ich interessierte mich nicht für einige Spalten des Ergebnisses, da sie bereits bekannte Werte hatten, die unter WHERE-Bedingungen verwendet wurden. Aber die SELECT (..., ..., ..., ...) FROM ... WHERE ... Variante hat mir keine Wörterbücher gegeben.

Beste Grüße! Harley

0
Hans Davidson

Um diese Funktion wie die MySQL-Version des Dictionary-Cursors auszuführen, müssen Sie sie in eine andere Funktion oder einen anderen Code einbetten. Ich werde in die Foren gehen und ihnen das für zukünftige Bereitstellungen ihres Codes vorschlagen, um ein Wörterbuch zurückzugeben, wenn der Aufruf von fetchall () mit dem Wörterbuchcursor verwendet wird. Hier ist ein Beispielcode, mit dem Sie das Problem beheben können:

cursor.execute(query)
# Python 2.7 and beyond with dictionary comprehension
results = [{key:value for key,value in row.iteritems()} for row in cursor]
# Python 2.6 and before
# results = [dict((key,value) for key,value in row.iteritems()) for row in cursor]

Durch diesen Code wird das gleiche Format verwendet wie die MySQL-Version des Wörterbuchcursors mit fetchall (). Sie sind sich nicht sicher, warum sie anders implementiert wurden. Dies hilft Ihnen jedoch, die gleiche Ausgabe eines tatsächlichen Python-Wörterbuchs anstelle einer Liste im Fall fetchall () zu erhalten.

0
Josh Williams