Code: Alles auswählen
self.cursor = self.conn.cursor( MySQLdb.cursors.DictCursor )
Code: Alles auswählen
self.cursor = self.conn.cursor( MySQLdb.cursors.DictCursor )
Code: Alles auswählen
Question:
How can I construct a dictionary out of the tuples returned by
.fetchxxx():
Answer:
There are several existing tools available which provide
helpers for this task. Most of them use the approach of using
the column names defined in the cursor attribute .description
as basis for the keys in the row dictionary.
Note that the reason for not extending the DB API specification
to also support dictionary return values for the .fetchxxx()
methods is that this approach has several drawbacks:
* Some databases don't support case-sensitive column names or
auto-convert them to all lowercase or all uppercase
characters.
* Columns in the result set which are generated by the query
(e.g. using SQL functions) don't map to table column names
and databases usually generate names for these columns in a
very database specific way.
As a result, accessing the columns through dictionary keys
varies between databases and makes writing portable code
impossible.
Code: Alles auswählen
from pysqlite2 import dbapi2 as sqlite
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
class DictCursor(sqlite.Cursor):
def __init__(self, *args, **kwargs):
sqlite.Cursor.__init__(self, *args, **kwargs)
self.row_factory = dict_factory
con = sqlite.connect(":memory:")
cur = con.cursor(factory=DictCursor)
cur.execute("select 1 as a")
print cur.fetchone()["a"]
Die Begründung ist schon korrekt.jens hat geschrieben:Wobei die Begründung doch eigendlich nicht einwandfei ist. Denn wenn ich mit SELECT mehrere Spalten haben will, gebe ich ja deren Namen an. Diese kann die API sich merken und aus den Ergebnissen dann ein Dict bauen... Ob dabei Groß- und Kleinschreibung evtl. von der DB nicht unterstützt wird, ist doch eigentlich egal. Zumindest mir!
OK, bei SELECT * FROM muß man auf die cursor.description zurückgreifen, aber ein * abfrage ist eh nicht die erste Sahne...ProgChild hat geschrieben:Deine anfrage kann die DB API auch nicht auswerten, da der Python Wrapper sonst selbst SQL verstehen müsste, was fast einer eigenen Datenbank gleich käme. Und erst recht hört das bei "SELECT * FROM ..." auf.
Code: Alles auswählen
""" schneller hack, um die daten als list von
dicts auszugeben
"""
import sqlite
dbh = sqlite.connect('./test.db') # database handle
statement = "select COL1,COL2,COL3 from SAMPLE_TAB" # statement
cursor = dbh.cursor()
cursor.execute(statement)
# tabellenname aus statement extrahieren
match = re.search(r'from\s([a-zA-Z_]+)', statement, re.I)
tablename = match.group(1)
# infos zur tabelle abfragen
c = dbh.cursor()
c.execute("pragma table_info(%s)" % tablename)
ret = c.fetchall()
fldlist = []
for field in ret:
fldlist.append(field[1])
c.close()
# unsere liste von dicts bauen
ret = []
for line in cursor.fetchall():
row = {}
for i in xrange(0, len(line)):
row[fldlist[i]] = line[i]
ret.append(row)
Und auf eine Tabelle mit mehr als 40 Spalten über die Indices zuzugreifen grenzt definitiv an Selbstmord. Wir hatten so ein Problem mal bei einem Kunden, die Tabelle hatte über 130 Spalten(Naja... die Datenbank war auch nicht wirklich normalisiert ), aber man ist froh, wenn man dann ein Dict hat.ProgChild hat geschrieben:Die Begründung ist schon korrekt.jens hat geschrieben:Wobei die Begründung doch eigendlich nicht einwandfei ist. Denn wenn ich mit SELECT mehrere Spalten haben will, gebe ich ja deren Namen an. Diese kann die API sich merken und aus den Ergebnissen dann ein Dict bauen... Ob dabei Groß- und Kleinschreibung evtl. von der DB nicht unterstützt wird, ist doch eigentlich egal. Zumindest mir!
Wenn die Groß- und Kleinschreibung verändert wird, so kann es sein, dass du eine Spalte in der einen Datenbank im Dict, um darauf zuzugreifen, mit einem komplett groß geschriebenen Wort in einer anderen Datenbank mit einem komplett klein geschriebenen Wort zugreifen. Nicht sehr portabel.