Hilfe bei Python skript

Gast #5010869
Lesenswert?

Hallo,
habe angefangen mit dem Code

1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3

4
import MySQLdb
5
import sys
6

7
try:
8
   con = MySQLdb.connect('localhost', 'michael', 'APD3dmQR', 'michael')
9
   cur = con.cursor()
10
   cur.execute("SELECT * FROM `deviceAttribute` ORDER BY `deviceId` ASC LIMIT 5")
11

12
   rows = cur.fetchall()
13

14
   for row in rows:
15
       print row["id"]
16

17
except MySQLdb.Error, e:
18

19
   print "Error %d: %s" % (e.args[0], e.args[1])
20
   sys.exit(1)
21

22
finally:
23

24
   if con:
25
       con.close()

allerdings bekomme ich nun folgenden Fehler:
1
Traceback (most recent call last):
2
 File "test.py", line 15, in <module>
3
   print row["id"]
4
TypeError: tuple indices must be integers, not str

Aber "id" ist vom Typ "int(10) unsigned" . Was ist falsch?
#5010901
Lesenswert?

Skriptanfänger schrieb:
>
1
>    for row in rows:
2
>        print row["id"]
3
>
>
> allerdings bekomme ich nun folgenden Fehler:
>
>
1
> Traceback (most recent call last):
2
>  File "test.py", line 15, in <module>
3
>    print row["id"]
4
> TypeError: tuple indices must be integers, not str
5
>
>
> Aber "id" ist vom Typ "int(10) unsigned" . Was ist falsch?

Was flashc ist, ist "row": das ist ein Tupel und kein Dict. Ein Tupel 
kann aber nur über den (Integer-)Index des gesuchten Elements 
angesprochen werden, Du hingegen versuchst, das mit einem Dict-Key zu 
machen, etwa so:
1
meinTupel = (1, 2, 3, 4)
2
print meinTupel['foo']

Du hast jetzt zwei Möglichkeiten: entweder Du benutzt Integer-Indizes, 
also statt 'row["id"]' eben 'row[0]' -- gesetzt, die Spalte 0 ist die 
Spalte, die Deine id enthält. Dann würde ich aber sicherstellen, daß die 
Spalte 0 auch tatsächlich die id enthält, also statt "SELECT * FROM" 
lieber etwas wie "SELECT id, ... FROM" schreiben -- sonst kann Dir das 
nämlich zu sehr interessanten Problemen kommen, wenn Du irgendwann mal 
die Struktur Deiner Tabelle änderst und id dann nicht mehr die erste 
Spalte ist.

Die andere Möglichkeit ist, einen DictCursor zu benutzen. wie ihn jeder 
DBAPI-2.0-kompatible Python-Datenbanktreiber anbietet. Dann erzeugst Du 
Deinen Cursor nicht mehr mit
1
curs = con.cursor()

sondern mit
1
curs = con.cursor(MySQLdb.cursors.DictCursor)

und erhälst dann als "row" keine Tupel mehr, sondern ein Dict.

Achtung: in Abhängigkeit von der abgefragten Datenmenge und der Anzahl 
und Länge Deiner Spaltennamen kann ein fetchall() auf einen DictCursor 
durchaus mehr Arbeitsspeicher benötigen als der Standard-Tuple-Cursor. 
Besser als
1
cur.execute(...)
2
res = cur.fetchall()
3
for row in rows:
4
    process(row)

ist daher meistens, das Iterator-Interface des Cursors zu benutzen:
1
cur.execute(...)
2
for row in cur:
3
    process(row)
Gast #5011202
Lesenswert?

Skriptanfänger schrieb:
> Also so?
>
>
1
> cur.execute(....)
2
> 
3
> row = cur.fetchone()
4
> while row is not None:
5
>          print row["id"]
6
>          row = cur.fetchone()
7
> 
8
> cur.close()
9
> conn.close()

Zum Beispiel. Aber Sheeva hat Dir ja gezeigt, daß Du die 
fetch*()-Methoden gar nicht brauchst und direkt über den Cursor 
iterieren kannst.
Gast #5011294
Lesenswert?

1
cur.execute(...)
2
for row in cur:
3
    process(row)
Wie kann ich da dann die einzelnen Felder anzeigen lassen?

Einfach
1
cur.execute(...)
2
for row in cur:
3
    process(row)
4

5

6
print(row["ID"])

?
Gast #5011317
Lesenswert?

Skriptanfänger schrieb:
> Wie kann ich da dann die einzelnen Felder anzeigen lassen?
>
> Einfach
>
1
> cur.execute(...)
2
> for row in cur:
3
>     process(row)
4
> 
5
> print(row["ID"])
6
> 
7
>
> ?

Exakt. Die "row" in "for row in cur" ist exakt dieselbe row, die Du mit 
"res = cur.fetchall(); for row in res: ..." erhälst.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren