141 votes

Comment puis-je obtenir un dict à partir d'une requête sqlite ?

db = sqlite.connect("test.sqlite")
res = db.execute("select * from table")

Avec l'itération, j'obtiens des listes correspondant aux rangées.

for row in res:
    print row

Je peux obtenir le nom des colonnes

col_name_list = [tuple[0] for tuple in res.description]

Mais existe-t-il une fonction ou un paramètre permettant d'obtenir des dictionnaires au lieu d'une liste ?

{'col1': 'value', 'col2': 'value'}

ou que je dois faire moi-même ?

0 votes

7 votes

@vy32 : Cette question date de juillet 2010, celle dont vous avez donné le lien date de novembre 2010. C'est donc celle-là qui est fausse. Et comme on peut s'y attendre, le commentaire inverse a été mis sur celle-là :-)

199voto

Alex Martelli Points 330805

Vous pourriez utiliser row_factory comme dans l'exemple de la documentation :

import sqlite3

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

con = sqlite3.connect(":memory:")
con.row_factory = dict_factory
cur = con.cursor()
cur.execute("select 1 as a")
print cur.fetchone()["a"]

ou suivez les conseils donnés juste après cet exemple dans la documentation :

Si retourner un tuple ne suffit pas et que vous souhaitez un accès par nom aux vous devriez envisager de définir row_factory à la version hautement optimisée de sqlite3.Row. Row fournit à la fois indexé et insensible à la casse et insensible à la casse pour les colonnes avec presque aucune surcharge de mémoire. Il sera probablement meilleure que votre propre approche personnalisée basée sur un dictionnaire ou ou même une solution basée sur db_row.

0 votes

Si les noms de vos colonnes contiennent des caractères spéciaux, par ex. SELECT 1 AS "dog[cat]" alors le cursor n'aura pas la description correcte pour créer un dict.

0 votes

J'ai mis connection.row_factory = sqlite3.Row et j'ai essayé connection.row_factory = dict_factory comme indiqué, mais cur.fetchall() me donne toujours une liste de tuples - une idée de la raison pour laquelle cela ne fonctionne pas ?

0 votes

@displayname, la documentation ne dit-elle pas "Il essaie d'imiter un tuple dans la plupart de ses fonctionnalités". Je suis presque sûr que c'est en quelque sorte similaire à ce que vous pouvez obtenir de collections.namedtuple . Lorsque j'utilise cur.fetchmany() Je reçois des entrées comme <sqlite3.Row object at 0x...> .

56voto

gandalf Points 1028

Je pensais répondre à cette question même si la réponse est partiellement mentionnée dans les réponses d'Adam Schmideg et d'Alex Martelli. Afin que d'autres personnes qui, comme moi, se posent la même question, puissent trouver la réponse facilement.

conn = sqlite3.connect(":memory:")

#This is the important part, here we are setting row_factory property of
#connection object to sqlite3.Row(sqlite3.Row is an implementation of
#row_factory)
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute('select * from stocks')

result = c.fetchall()
#returns a list of dictionaries, each item in list(each dictionary)
#represents a row of the table

22voto

bbengfort Points 451

Même en utilisant la classe sqlite3.Row, vous ne pouvez toujours pas utiliser le formatage des chaînes sous la forme de :

print "%(id)i - %(name)s: %(value)s" % row

Afin de contourner ce problème, j'utilise une fonction d'aide qui prend la ligne et la convertit en dictionnaire. Je ne l'utilise que lorsque l'objet dictionnaire est préférable à l'objet Row (par exemple, pour des choses comme le formatage des chaînes de caractères, lorsque l'objet Row ne prend pas en charge l'API dictionnaire de manière native). Mais j'utilise l'objet Row le reste du temps.

def dict_from_row(row):
    return dict(zip(row.keys(), row))

10 votes

Sqlite3.Row met en œuvre le protocole de mappage. Vous pouvez simplement faire print "%(id)i - %(name)s: %(value)s" % dict(row)

15voto

Lukasz Czerwinski Points 1098

Après vous être connecté à SQLite : con = sqlite3.connect(.....) il suffit de courir :

con.row_factory = sqlite3.Row

Voilà !

8voto

De PEP 249 :

Question: 

   How can I construct a dictionary out of the tuples returned by
   .fetch*():

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 .fetch*()
   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.

Alors oui, faites-le vous-même.

0 votes

> varie selon les bases de données - comme quoi, sqlite 3.7 et 3.8 ?

0 votes

@user1123466 : ... Comme entre SQLite, MySQL, Postgres, Oracle, MS SQL Server, Firebird...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X