PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Python: Ergebnisse von Threads auswerten...


Magnum
03.08.2005, 13:00
Hallo,
in einem Python Programm würde ich gerne Threads benutzen, weil ich mehrmal dieselbe Aufgabe erledigen lassen möchte, wobei es bei jeder Ausführung zu Wartezeiten kommt. Meine Idee ist nun, wenn das mit Threads läuft warten die Threads gleichzeitig, sodass das Programm viel schneller fertig ist.
Das Problem ist nun: Wie speichert man die Ergebnisse der einzelnen Threads zentral ab um sie dann weiterverarbeiten zu können?

import thread

def print_time(start, erg):
# was machen, was lange dauert....
# Ergenis speichern
erg[start] = start + 1


global erg
erg = {}

# Starte die neuen Threads
thread.start_new_thread( print_time, (1, erg) )
print 'erster'
thread.start_new_thread( print_time, (2, erg) )
print 'zweiter'
thread.start_new_thread( print_time, (3, erg) )
print 'dritter'

# zentralen AUsgabe aller Ergebnisse
print erg

Folgende AUsgabe erscheint:
D:\>python test.py
erster
zweiter
dritter
{}

Also schreiben die Threads nicht das Ergebnis in erg.

Es sollte so aussehen, dass im erg-Dictionary folgendes steht
erg[1] == 2
erg[2] == 3
erg[3] == 4

Hat jemand eine Idee wie man sowas realisieren kann?

Grüße
Magnum


TheBee
04.08.2005, 18:41
Hallo,

Du hast ein klassisches Synchronisationsproblem. Dein Script ist bereits beendet, bevor die Threads ausgeführt werden. Das lässt sich recht einfach nachvollziehen: Führe das Script mal Zeile für Zeile in der Interaktiven PythonShell aus, dann erhälst du das gewünschte Ergebnis.

Du musst also auf die Beendigung der Threads warten.
Das beste ist, du nimmst das threading Modul und daraus die Thread bzw. Lock Klasse.

Du erzeugst ein Lock (z.B. ergLock) um die Zugriffe auf die Variable zu Synchronisieren und übergibst es als Parameter an die Threadfunktion. Du willst ja nicht mit zwei Threads gleichzeitig auf die Variable zugreifen.

Du musst ab sofort vor jedem Zugriff zuerst ergLock.acquire() aufrufen und nach dem Zugriff das Lock mit ergLock.release() wieder freigeben.

Einen Thread erzeugst du dann mit:
t1 = threading.Thread(target=print_time, args=(1, erg, ergLock))

Dann noch mit t1.start() starten und vor Ende des Programms (und natürlich auch vor der Ausgabe von erg) auf die Beendigung mit t1.join() warten.

Threads können einem ganz schön das Hirn verbiegen. :D

Magnum
05.08.2005, 23:37
Hallo TheBee,
danke für die Antwort.
Ich habe in deiner Antwort zwar verstanden wo mein Problem liegt, aber nicht wirklich eine Ahnung wie das nun konkret richtig implementiert wird.

Werde mich die Tage durch einige von Google gefundenen Beispiele kämpfen. Oder hat jemand ein deutsches oder notfalls auch englisches Tutorial zum modul threading zur Hand?

Magnum

Magnum
06.08.2005, 15:13
Hab nun mal einen Programmteil gepostet, der nicht läuft:
Python sagt:
C:\test>python test.py
File "test.py", line 14
offenePorts = []
^
SyntaxError: invalid syntax

An dieser Stelle erstelle ich einfach nur eine leere Liste, was ist daran falsch?

Die Portscanns dauern je nach Port- und Hostanzahl recht lange, weil wenn ein Port nicht offen ist ein bestimmtes Timeout gewartet wird.

import socket, thread, time

# Porttupel
PORTS = ( (21,'FTP'), (22,'SSH'), (23,'Telnet'), (80,'HTTP'), (4711,'emule-HTTP') )

#SLEEPTIME = 2

def scanPorts( ip, allHosts, lock, *args ):
# TCP-Socket aufmachen
sockFD = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Liste der offenen Ports
offenePorts = []
for port in PORTS:
try:
sockFD.connect( ip, port[0] )
offenePorts.append( port[0] )
except:

# Socket schliessen
sockFD.close()

# Sperre erlangen
lock.acquire()
# Ergebnis schreiben
allHosts[ip] = offenePorts
# Sperre freigeben
lock.release()

if __name__=="__main__":
# Sperre
lock = thread.allocate_lock()
# Liste der Threads
myThreads = []
# Ergebnis Dictionary
allHosts = {}

# Threads starten
for x in range(1, 11, 1):
ip = '192.168.0.' + str(x)
myThreads.append( thread.start_new_thread( scanPorts,(ip,allHosts,lock) ) )

# Warten bis alle Threads fertig sind
for t in myThreads:
t.join()

# Ausgabe
for host in allHosts:
print host, allHosts[host]

print "fertig! :-)"

Magnum