Forum: PC-Programmierung Hilfe bei Python skript


von Skriptanfänger (Gast)


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?

von M. K. (kichi)


Lesenswert?

Skriptanfänger schrieb:
> ["id"]
Ist in dieser Form ein string. Hat er dir ja auch gesagt. Mach mal
1
print(type("id"))
dann siehst du es.

: Bearbeitet durch User
von Sheeva P. (sheevaplug)


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)

von Skriptanfänger (Gast)


Lesenswert?

Also so?

[code]
cur.execute(....)

row = cur.fetchone()
while row is not None:
         print row["id"]
         row = cur.fetchone()

cur.close()
conn.close()

von Karl Käfer (Gast)


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.

von Skriptanfänger (Gast)


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"])

?

von Karl Käfer (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.