2013-01-07 5 views
5

mam kod jak poniżej:Fetchall zwraca tylko jedną kolumnę w Pythonie?

db = MySQLdb.connect(user='root', db='galaxy', passwd='devil', host='localhost') 
cursor = db.cursor() 
cursor.execute('SELECT username, password FROM galaxy_user') 
names = [row[0] for row in cursor.fetchall()] 
passw = [password[1] for password in cursor.fetchall()] 
db.close() 

Problemem jest to, mogę tylko dostępu albo nazwy lub hasło zakaz z następującego kodu. Dzięki temu mogę uzyskać tylko nazwę użytkownika. Otrzymuję pustą listę dla passw. Teraz jeśli zmienię to na:

passw = [row[1] for row in cursor.fetchall()] 
names = [password[1] for password in cursor.fetchall() 

Otrzymuję wartość passw, ale nazwy są pustą listą. Co się dzieje?

Odpowiedz

13

Po każdym cursor.execute można użyć tylko jeden raz cursor.fetchall. To "wyczerpuje" kursor, pobiera wszystkie jego dane, a następnie nie można go ponownie "odczytać".

z następującego kodu czytasz wszystkie dane w tym samym czasie:

db = MySQLdb.connect(user='root', db='galaxy', passwd='devil', host='localhost') 
cursor = db.cursor() 
cursor.execute('SELECT username, password FROM galaxy_user') 
names, passw = zip(*cursor.fetchall()) 
db.close() 

Inną możliwością byłoby do przechowywania wszystkich danych na liście, a następnie odczytać je tak, jakby były kursor:

records = cursor.fetchall() 
names = [record[0] for record in records] 
passw = [record[1] for record in records] 

A może słownik (nazwa -> hasło)?

user_pass = dict(cursor.fetchall()) 

lub po prostu (jak @JonClemens sugerowane):

user_pass = dict(cursor) 
+2

Myślę, że kluczem jest to, że '.fetchall()' wydaje się nieco zbędny, ponieważ kursor powinien być iterable ... albo, 'list (cursor)' lub lubię twój pomysł 'dict (cursor)' :) –

+0

@eumiro, Właśnie testowałem używając Pythona cx_Oracle: records = cursor.fetchall() names = [record [0] dla rekordów w rekordach] passw = [record [1] dla rekordów w rekordach] a nazwa to None. Dzięki – Frank