web-dev-qa-db-fra.com

cursor.fetchall () vs list (curseur) dans Python

Les deux méthodes renvoient une liste des éléments retournés de la requête. Ai-je oublié quelque chose ici?
Ou ont-ils des usages identiques?
Des différences en termes de performances?

34
NZal

Si vous utilisez le curseur par défaut, un MySQLdb.cursors.Cursor, l'intégralité du jeu de résultats sera stocké côté client (c'est-à-dire dans une liste Python) au moment où la cursor.execute() est terminée.

Par conséquent, même si vous utilisez

for row in cursor:

vous n'obtiendrez aucune réduction de l'empreinte mémoire. L'ensemble de résultats complet a déjà été stocké dans une liste (voir self._rows Dans MySQLdb/cursors.py).

Toutefois, si vous utilisez un SSCursor ou un SSDictCursor:

import MySQLdb
import MySQLdb.cursors as cursors

conn = MySQLdb.connect(..., cursorclass=cursors.SSCursor)

then le jeu de résultats est stocké sur le serveur, mysqld. Maintenant tu peux écrire

cursor = conn.cursor()
cursor.execute('SELECT * FROM HUGETABLE')
for row in cursor:
    print(row)

et les lignes seront extraites une à une du serveur, ne nécessitant donc pas de Python pour construire une grande liste de n-uplets en premier et économiser ainsi de la mémoire.

Sinon, comme d'autres l'ont déjà indiqué, cursor.fetchall() et list(cursor) sont essentiellement identiques.

67
unutbu

cursor.fetchall() et list(cursor) sont essentiellement les mêmes. L'option différente est de ne pas récupérer une liste, mais simplement de passer en boucle sur l'objet curseur nu:

for result in cursor:

Cela peut être plus efficace si le jeu de résultats est volumineux, car il n'a pas besoin d'extraire l'intégralité du jeu de résultats et de tout conserver en mémoire. il peut simplement obtenir progressivement chaque élément (ou les grouper par lots plus petits).

11
Amber

Une différence (spécifique à MySQLdb/PyMySQL) à noter lorsque vous utilisez DictCursor est que list(cursor) vous donnera toujours une liste, tandis que cursor.fetchall() vous donnera une liste sauf si le jeu de résultats est vide, auquel cas il vous donne un tuple vide. Ce fut le cas dans MySQLdb et reste le cas dans le plus récent PyMySQL , où il ne sera pas corrigé pour des raisons de compatibilité ascendante. Bien que ceci ce n'est pas une violation de Python , c'est toujours surprenant et peut facilement conduire à une erreur de type provoquée en supposant à tort que le résultat est un liste , plutôt que juste une séquence .

Compte tenu de ce qui précède, je suggère de toujours privilégier list(cursor) par rapport à cursor.fetchall(), afin d'éviter de se faire prendre par une erreur de type mystérieuse dans le cas Edge où votre jeu de résultats est vide.

4
Mark Amery

list(cursor) fonctionne parce qu'un curseur est un itératif; vous pouvez aussi utiliser cursor dans une boucle:

for row in cursor:
    # ...

Une bonne implémentation d'adaptateur de base de données récupérera des lignes par lots sur le serveur, ce qui économisera sur l'encombrement mémoire requis car il n'aura pas besoin de conserver le jeu de résultats full en mémoire. cursor.fetchall()has pour renvoyer la liste complète à la place.

Il est inutile d'utiliser list(cursor) sur cursor.fetchall(); l’effet final est alors effectivement le même, mais vous avez perdu l’occasion de diffuser les résultats.

2
Martijn Pieters