pysqlite2 hat kein DictCursor ???

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 13. September 2005, 14:31

Mit MySQLdb erstelle ich das Cursor-Objekt so:

Code: Alles auswählen

self.cursor         = self.conn.cursor( MySQLdb.cursors.DictCursor )
Ist cursors.DictCursor eine Eigenschaft die pysqlite2 nicht hat???

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
raist1314
User
Beiträge: 52
Registriert: Dienstag 21. September 2004, 06:58
Wohnort: Adelzhausen
Kontaktdaten:

Dienstag 13. September 2005, 15:26

scheint so, dass es nicht geht, hab eben nochmal die Doku gewälzt. Ich hatte mal das gleiche Problem, hab mir dann aber was gebastelt, um an sowas wie Deinen DictCursor zu kommen. Leider sitz ich in nem total beschissenem Internetcafe.... Ich werde versuchen, meinen Code heute abend mal zu posten.... wie gesagt... ist nur ein schneller hack...

Sebastian
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 13. September 2005, 15:42

Das wäre super, ohne dem wäre ein einbau in PyLucid recht kompliziert :(

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Dienstag 13. September 2005, 22:07

`DictCursor` gehört nicht zur DB API. Auszug aus PEP 249

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.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 14. September 2005, 06:16

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!

Naja, ich könnte das natürlich in meinem SQL-Wrapper selbst erledigen ;)

Wie kann man sicher abfragen, ob ein Dictcursor vorhanden ist? Einfach mit try versuchen ihn anzusprechen? Ist er überhaupt bei irgendeinem anderen API vorhanden oder nur bei MySQLdb?

EDIT:
Ich sehe gerade im PySQLite Usage Guide ein Listing:

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"]
Wobei hier cursor.description genommen wird.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ProgChild
User
Beiträge: 210
Registriert: Samstag 9. April 2005, 10:58
Kontaktdaten:

Mittwoch 14. September 2005, 13:51

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!
Die Begründung ist schon korrekt.

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.

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.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 14. September 2005, 13:56

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.
OK, bei SELECT * FROM muß man auf die cursor.description zurückgreifen, aber ein * abfrage ist eh nicht die erste Sahne...
Ansonsten baue ich in meinem Wrapper ja den Befehl zusammen und da weiß ich halt die verlangten Spaltennamen.

Aber im Kontreten Fall von SQLite: Unterscheidet diese denn in Groß-, Kleinschreibung???

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
raist1314
User
Beiträge: 52
Registriert: Dienstag 21. September 2004, 06:58
Wohnort: Adelzhausen
Kontaktdaten:

Mittwoch 14. September 2005, 18:38

Hier mal mein Code zu dem Thema, wie gesagt, es ist ein schneller Hack von mir, funktioniert aber soweit. Ich hab den Code bei mir im Projekt im Einsatz zum Testen, hab mir nämlich selber sowas wie ne DBAPI gebastelt. Ich benutze es in einigen richtig grossen Projekten und habe Unterstützung für die wichtigsten Datenbanken drin, wie gesagt, sqlite benutze ich intern zum Testen.

Blabla... viel gerede.... hier der Code (bisschen abgewandelt, da das ganze als Methode in einer Klasse steckt)

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)
Für Anregungen bin ich immer dankbar, hoffe ich konnte Dir helfen.

Sebastian
Zuletzt geändert von raist1314 am Donnerstag 15. September 2005, 06:38, insgesamt 1-mal geändert.
raist1314
User
Beiträge: 52
Registriert: Dienstag 21. September 2004, 06:58
Wohnort: Adelzhausen
Kontaktdaten:

Mittwoch 14. September 2005, 18:43

ProgChild hat geschrieben:
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!
Die Begründung ist schon korrekt.

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.
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.

Sebastian
Antworten