Forum: PC-Programmierung Python: Thread innerhalb einer Klasse durch Dekonstruktor beenden


von Matt B. (mattb)


Lesenswert?

Hallo,

ich programmiere an einem kleinen Python Programm, das auch einen TCP
Server beinhaltet. Der Code des Servers liegt in einer Klasse und läuft
als Thread. Das Problem ist nun, dass beim Löschen der Klasse der
Dekonstruktor nicht (oder nicht korrekt) aufgerufen wird.

Codeausschnitt, der auf den Client wartet:
1
while True:
2
            print ('waiting for clients...')
3
            clientsock, addr =  TCPServer.SERVER.accept()
4
            print '...connected from:', addr
5
            thread.start_new_thread(__ClientHandler, (clientsock, addr))

Dekonstruktor der Klasse:
1
def __del__(self):
2
        print ('Server wurde beendet')
3
        return

Wenn ich die Klasse in meinem Hauptprogramm mit dem Befehl
1
del cls_Server
lösche, erwartete ich, dass in der Konsole "Server wurde beendet"
erscheint. Das ist aber nicht der Fall. Ich denke das liegt an dem
laufenden Thread. Daher will ich diesen manuell beenden.

Eine Abfrage eines Flags innerhalb der While-Schleife geht nicht, da der
Server bei der Zeile
1
clientsock, addr =  TCPServer.SERVER.accept()
so lange stehen bleibt, bis sich ein Client angemeldet hat.

Welche Möglichkeiten gibt es noch?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Matt B. schrieb:
> Eine Abfrage eines Flags innerhalb der While-Schleife geht nicht, da der
> Server bei der Zeile

Sicher? Normalerweise wird da eine Exception geworfen, gibt es bei dem 
Thread eventuell eine interrupt() Methode? Die sollte für genau solche 
blockierende Aktionen dafür sorgen das der "Warte-Schlaf" unterbrochen 
wird und du dann ggf. reagieren kannst, also:
- Flag setzen
- thread.interrupt() aufrufen
- ggf. Exceptions behandlen (Interrupted, IO...)

von Matt B. (mattb)


Lesenswert?

Ich habe bei dem Server jetzt ein Timeout definiert. Das heisst jede 
Sekunde läuft dieser ab und es wird eine Exception geworfen.

[code]
TCPServer.SERVER.settimeout(1)
print ('waiting for clients...')
while TCPServer.RUN == True:
            try:
                clientsock, addr =  TCPServer.SERVER.accept()
                print '...connected from:', addr
                thread.start_new_thread(__ClientHandler, (clientsock, 
addr))
            except Exception as e:
                pass
[code]

Anschließend wird die While-Schleife von neuem durchloffen, wodurch das 
Flag TCPServer.RUN geprüft werden kann.

Das einzige was nicht noch stört, ist dass solange ein Thread in der 
Klasse läuft, der Dekonstruktor nicht aufgerufen wird. Ich muss also 
"manuell" eine eigene Methode aufrufen, welche mir das Flag 
TCPServer.RUN auf False setzt.
Es funktioniert auch nicht, wenn ich diese Methode im Dekonstruktor 
aufrufe.

Ich würde aber für das Beenden des Servers einfach den Dekonstruktor die 
Arbeit machen lassen.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Scheint mir jetzt nicht so gut... Hast du den schon versucht einfach den 
(Server-)Socket zu schließen?

von Matt B. (mattb)


Lesenswert?

Wenn ich den Socket schließe obwohl die While-Schleife noch läuft wird 
eine Exception ausgelöst. Deshalb ist mir lieber, wenn die Schleife 
unterbrochen und der Socket anschließend beendet wird.
1
TCPServer.RUNNING = True
2
        while TCPServer.RUN == True:
3
            try:
4
                clientsock, addr =  TCPServer.SERVER.accept()
5
                print '...connected from:', addr
6
                thread.start_new_thread(__ClientHandler, (clientsock, addr))
7
            except Exception as e:
8
                pass
9
        TCPServer.RUNNING = False
10
        TCPServer.SERVER.close()

Ich habe auch versucht, den Socket innerhalb des Dekonstruktors zu 
beenden. Aber so wie ich vorher geschrieben hab, wird der Dekonstruktor 
nicht ausgefährt, solange in der Klasse ein Thread läuft. Funktioniert 
also nicht.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Matt B. schrieb:
> Wenn ich den Socket schließe obwohl die While-Schleife noch läuft wird
> eine Exception ausgelöst.

Aber genau das ist doch Sinn und Zweck der Sache...
Am besten wäre du verpasst deiner Klasse eine close Methode die das 
Kapselt:
- Flag setzen
- Socket schließen

Dann kannst du deinen Thread sauber beenden.

Matt B. schrieb:
> Deshalb ist mir lieber, wenn die Schleife unterbrochen und der Socket
> anschließend beendet wird

Wieso? Was ist der Vorteil der Methode?

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.