lastrowid außerhalb der Reihe

13/01/2009 - 20:22 von Florian Lindner | Report spam
Hallo,

ich habe folgenden Code
:
for i, weight in enumerate(self.weightValue):
weightStr = str(weight).rjust(4,"0")
weightStr = weightStr[:3] + "." + weightStr[-1:]
ret = cursor.execute(INSERT_SQL, (self.patientID,
self.deviceID, weightStr, self.timeMeasured[i]))
self.conn.commit()

lastrow = cursor.lastrowid
url_call = lambda: urllib.urlopen(NOTIFY_URL %
lastrow).read()
t = threading.Thread(target = url_call)
t.daemon = True
t.start()

Sinn und Zweck ist, dass nach hinzufügen eines Datensatzen der
Webserver davon benachrichtigt wird. Da das Program nicht blocken
soll, starte ich dafür einen neuen Thread. Von lastrowid erwarte ich
die Primàrschlüssel ID (auto increment) des neuen Datensatzes. Die
Datenbank ist MySQL 5.0. Meistens klappt das auch (man sieht es im Log
an den stetig steigenden IDs) vereinzelt werden aber IDs an den
Webserver gemeldet, denen kein Datensatz zugeordnet ist und die auch
nicht in der Reihe sind.
Eingebettet ist das Stück in Code in einem MultiThreaded Servers auf
Basis von SocketServer.

Könnte das irgendwie an diesem Code liegen? Probleme mit Threads?

Danke,

Florian
 

Lesen sie die antworten

#1 Diez B. Roggisch
14/01/2009 - 00:27 | Warnen spam
Florian Lindner schrieb:
Hallo,

ich habe folgenden Code
:
for i, weight in enumerate(self.weightValue):
weightStr = str(weight).rjust(4,"0")
weightStr = weightStr[:3] + "." + weightStr[-1:]
ret = cursor.execute(INSERT_SQL, (self.patientID,
self.deviceID, weightStr, self.timeMeasured[i]))
self.conn.commit()

lastrow = cursor.lastrowid
url_call = lambda: urllib.urlopen(NOTIFY_URL %
lastrow).read()



Wieso weist du das lambda einem namen zu? Ein

def url_call():
...

waere klarer. Lambdas mit Namen sind etwas sinnfrei. Dazu hat man
eingebettet Funktionen.

Aber das natuerlich nur am Rande.

t = threading.Thread(target = url_call)
t.daemon = True
t.start()

Sinn und Zweck ist, dass nach hinzufügen eines Datensatzen der
Webserver davon benachrichtigt wird. Da das Program nicht blocken
soll, starte ich dafür einen neuen Thread. Von lastrowid erwarte ich
die Primàrschlüssel ID (auto increment) des neuen Datensatzes. Die
Datenbank ist MySQL 5.0. Meistens klappt das auch (man sieht es im Log
an den stetig steigenden IDs) vereinzelt werden aber IDs an den
Webserver gemeldet, denen kein Datensatz zugeordnet ist und die auch
nicht in der Reihe sind.
Eingebettet ist das Stück in Code in einem MultiThreaded Servers auf
Basis von SocketServer.

Könnte das irgendwie an diesem Code liegen? Probleme mit Threads?




Ich finde den bedenklich, aus einer Reihe von gruenden. Zum einen ist er
schlicht fehlerhaft. Wenn naemlich - warum auch immer - der Start des
Thread sich etwas verzoegert (wohlgemerkt des thread - t.start() ist
dann schon vorbei), dann kann es sein, das lastrow schon mit einem
anderen Wert belegt ist. Und weil du den Wert lastrow nicht in einem
closure mit dem lambda einfaengst, koennte das Aussetzer in deinen
Sequenzen produzieren.

Zum anderen bist du sehr verschwenderisch. Statt vielen Threads solltest
du einen aufmachen, und den mit einer Queue fuettern. Etwa so:

q = Queue.Queue()

def url_call():
while True:
item = q.get()
if item is None:
break
urllib.urlopen(NOTIFY_URL % item).read()

t = Thread(target=url_call)
t.start()

for
...
q.put(cursor.lastrowid)

q.put(None) # thread sentinel zum beenden

Allerdings hat das nix mit deinem eigentlichen Problem zu tun. Um das
anzugehen wuerde ich mir mal einfach mitloggen lassen (synchron) was
denn fuer ids generiert werden. Wenn das dieselben sind (ich sehe nichts
warum dem nicht so sein sollte, wie gesagt - *fehlen* koennten welche)
dann weisst du es liegt nicht am threading code.

Ist aber auch eh unwahrscheinlich - warum sollte der sich daten ausdenken?

Kann es sein, das die Rows geloescht werden von einem anderen Prozess?
Oder das statement fehlschlaegt, aber eben doch eine ID vergeben wurde
(was nicht mehr rueckgaenging machbar ist)?

Diez

Ähnliche fragen