web-dev-qa-db-fra.com

Sqlite et Python - retourne un dictionnaire en utilisant fetchone ()?

J'utilise sqlite3 dans Python 2.5. J'ai créé un tableau qui ressemble à ceci:

   create table votes (
      bill text,
      senator_id text,
      vote text)

J'y accède avec quelque chose comme ça:

v_cur.execute("select * from votes")
row = v_cur.fetchone()
bill = row[0]
senator_id = row[1]
vote = row[2]

Ce que j'aimerais pouvoir faire, c'est que fetchone (ou une autre méthode) retourne un dictionnaire plutôt qu'une liste, afin que je puisse faire référence au champ par son nom plutôt que par sa position. Par exemple:

bill = row['bill'] 
senator_id = row['senator_id']
vote = row['vote']

Je sais que vous pouvez le faire avec MySQL, mais est-ce que quelqu'un sait comment le faire avec SQLite?

Merci!!!

26
AndrewO

La façon dont j'ai fait cela dans le passé:

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

Ensuite, vous le configurez dans votre connexion:

from pysqlite2 import dbapi2 as sqlite
conn = sqlite.connect(...)
conn.row_factory = dict_factory

Cela fonctionne sous pysqlite-2.4.1 et python 2.5.4.

18
Colin Burnett

Il existe actuellement une option pour cela dans sqlite3. Modifiez le membre row_factory de l'objet de connexion en sqlite3.Row:

conn = sqlite3.connect('db', row_factory=sqlite3.Row)

ou

conn.row_factory = sqlite3.Row

Cela vous permettra d'accéder aux éléments de la ligne par nom - style dictionnaire - ou par index. C'est beaucoup plus efficace que de créer votre propre solution de contournement.

73
Eric

J'essayais récemment de faire quelque chose de similaire en utilisant sqlite3.Row (). Bien que sqlite3.Row () soit idéal pour fournir une interface de type dictionnaire ou une interface de type Tuple, cela ne fonctionnait pas lorsque j'ai transféré la ligne avec ** kwargs. Donc, avait besoin d'un moyen rapide de le convertir en dictionnaire. J'ai réalisé que l'objet Row () peut être converti en dictionnaire simplement en utilisant itertools.

Python 2:

db.row_factory = sqlite3.Row
dbCursor = db.cursor()
dbCursor.execute("SELECT * FROM table")
row = dbCursor.fetchone()

rowDict = dict(itertools.izip(row.keys(), row))

Ou en Python 3, plus simplement:

dbCursor = db.cursor()
dbCursor.execute("SELECT * FROM table")
row = dbCursor.fetchone()
rowDict = dict(Zip([c[0] for c in dbCursor.description], row))

De même, vous pouvez utiliser la commande dbCursor.fetchall () et convertir l'ensemble des lignes en liste de dictionnaires dans une boucle for.

9
lexxonnet

Bien sûr, faites-vous un DictConnection et un DictCursor comme expliqué et montré à http://trac.edgewall.org/pysqlite.org-mirror/wiki/PysqliteFactories par exemple.

5
Alex Martelli

Je sais que vous ne posez pas cette question, mais pourquoi ne pas simplement utiliser sqlalchemy pour créer un orme pour la base de données? alors vous pouvez faire des choses comme


entry = model.Session.query(model.Votes).first()
print entry.bill, entry.senator_id, entry.vote

en prime, votre code sera facilement transférable à une autre base de données, et les connexions, entre autres, seront gérées gratuitement.

2
si28719e

J'ai utilisé ceci:

def get_dict(sql):
    return dict(c.execute(sql,()).fetchall())

Ensuite, vous pouvez faire ceci:

c = conn.cursor()
d = get_dict("select user,city from vals where user like 'a%'");

Maintenant, d est un dictionnaire où les clés sont user et les valeurs sont city. Cela fonctionne aussi pour group by

1
vy32

J'utilise quelque chose comme ça:

class SqliteRow(object):
    def __init__(self):
        self.fields = []

    def add_field(self, name, value):
        self.fields.append(name)
        setattr(self, name, value)

    def to_Tuple(self):
        return Tuple([getattr(self, x) for x in self.fields])

avec ça:

def myobject_factory(cursor, row):
    myobject= MyObject()
    for idx, col in enumerate(cursor.description):
        name, value = (col[0], row[idx])

        myobject.add_field(name, value)
    return myobject

MyObject() est une classe qui hérite de SqliteRow. La classe SqliteRow est une classe de base pour chaque objet que je souhaite renvoyer par une requête. Chaque colonne devient un attribut et est connectée à la liste fields. . La fonction to_Tuple permet de modifier l’objet entier en un formulaire adapté aux requêtes (il suffit de transmettre l’objet entier et de l’oublier). 

Pour obtenir différents types de classe de cette fonction. Vous devez créer un objet fabrique, qui générera des objets en fonction de la liste des champs (par exemple: dict with {some_unique_value_made_of_fields: class})

De cette façon, je reçois un simple ORM.

0
red777