Thread abbrechen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Markus12
User
Beiträge: 195
Registriert: Dienstag 6. März 2007, 19:32
Wohnort: Frankfurt am Main

Hallo Freunde,
In einem meiner Programme muss ich einen Thread abbrechen... Nur kann ich keine Funktion finden, die dies tut. Ich kann dies auch nicht erreichen, indem ich in eine Variable anders setze, die dann die Schleife beendet, denn in dem Thread gibt es keine Schleife...

Ich würde gerne also eine Funktion wissen, die den Thread gnandenlos abbricht^^ Wäre sehr froh darüber, wenn mir jemand aushelfen könnte :)

Danke schon mal im Voraus!
Suchen im Internet haben mir leider nicht weitergebracht...

Grüße Markus :)
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Der sauberste Weg ist sowas über einen Event zu realisieren.
Einen Thread kann man nicht von aussen abbrechen.

Beispiel:

Code: Alles auswählen

In [2]: import threading
In [3]: import time
In [4]: event = threading.Event()


In [5]: def func(event):
   ...:     while not event.isSet():
   ...:         print "arbeite"
   ...:         time.sleep(1)
   ...:     print "quit"
   ...:
   ...:

In [7]: t = threading.Thread(target=func, args=(event,))

In [8]: t.start()
arbeite

In [9]: event.set()
quit
BlackJack

@Markus12: Wenn es keine Schleife gibt, was wird denn dann gemacht, das man unterbrechen muss?
Markus12
User
Beiträge: 195
Registriert: Dienstag 6. März 2007, 19:32
Wohnort: Frankfurt am Main

@Blackjack:
Bei meinem internen Prozess ist es "nur" zum Beispiel das Laden einer großen Datei, die mehrere Megabyte umfasst und das dauert ggf. einige Minuten zum Laden... Deshalb muss das vom Interface per Button abbrechbar sein, zumindest möchte ich das so.


@Zap:
Danke für das Beispiel Zap, hat mir sehr geholfen, habe ich umgesetzt. Nun gibt es allerdings einen anderen Fehler in meinem Programm.
Nebenbei habe ich eine Subklasse erstellt, den ich als Thread benutze, aber das ist nicht so wichtig, nehme ich mal an.


Der Thread führt grob gesagt eine funktion aus, die eine Datei aus dem Internet lädt; mit folgender Funktion:

Code: Alles auswählen

urllib.urlretrieve(url=meineURL, filename=meinPfad)
Der wird auch abgebrochen, das Programm hängt sich nicht mehr auf, wenn man im Fenster auf das rote X klickt und das Fenster schließt.
Nun aber das Problem, dass die Datei anscheinend noch nicht geschlossen ist, denn in meinem Programm soll die Datei, die heruntergeladen wird, was allerdings abgebrochen wird, gelöscht werden, da sie nicht komplett ist... Es gibt einen Windows Error, und der sagt mir:

Code: Alles auswählen

WindowsError: [Error 32] Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird
Gibt es eine Möglichkeit, das zu lösen?

Grüße Markus :)
BlackJack

@Markus12: `urllib.urlretrieve()` kennt das Event doch gar nicht, wie kann da ein Thread der das ausführt abgebrochen werden!? Der läuft weiter würde ich sagen, und deshalb ist auch die Datei noch offen und kann nicht gelöscht werden.
Markus12
User
Beiträge: 195
Registriert: Dienstag 6. März 2007, 19:32
Wohnort: Frankfurt am Main

Hi Blackjack,
Wie meinst du das? Welches Event kennt nicht urllib.urlretrieve?
Das verstehe ich nicht.
Habe es überprüft. Die Datei wird weiterhin heruntergeladen, und nicht abgebrochen, obwohl ich mir das nicht erklären kann.

Was ist überhaupt threading.Event!? und wieso kann man es mit der set-methode abbrechen?
Und wieso kennt eine Event-Klasse kein urlretrieve oder wie sollte es es denn kennen? ^^

Leider sind diese Tuturials ziemlich schlecht, als dass man das alles verstehen könnte... Sollte nicht stunden dauern, damit man soetwas kleines versteht.

Viele Grüße Markus :)
BlackJack

@Markus12: Jetzt verwirrst Du mich gerade. Du hast behauptet der Thread wird abgebrochen, was nicht sein kann, weil `urllib.urlretrieve()` eben nicht so einfach abgebrochen werden kann. Was Du ja im letzten Beitrag auch bestätigst.

Man kann Threads nicht ohne weiteres von aussen beenden, der Code im Thread muss das selber tun. Wenn man also einen Thread haben möchte, den man von aussen beenden kann, geht das nur, wenn der Code im Thread irgend wie auf eine Abbruchbedingung von aussen reagiert, in dem zum Beispiel regelmässig ein Flag oder ein `Event` geprüft wird.
Markus12
User
Beiträge: 195
Registriert: Dienstag 6. März 2007, 19:32
Wohnort: Frankfurt am Main

Ich dachte, er würde abgebrochen werden, was aber nicht der Fall war.
Mit einer Bedingung, das wusste ich bereits, ist ja Basic-knowledge.

Wenn das sonst nicht möglich ist, ist es schade... Warum sollte sowas theoretisch nicht möglich sein?

Du hattest Recht, er würde nicht beendet. Aber wie soll ich denn eine Funktion abbrechen, die - wie in meinem Fall - eine funktion ausführt wie das herunterladen einer datei...?

Viele Grüße Markus :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Markus12 hat geschrieben:Aber wie soll ich denn eine Funktion abbrechen, die - wie in meinem Fall - eine funktion ausführt wie das herunterladen einer datei...?
In dem sie immer einen Block lädt, Bedingung prüft, Block lädt, Bedingung prüft, Block lädt.. etc.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Markus12
User
Beiträge: 195
Registriert: Dienstag 6. März 2007, 19:32
Wohnort: Frankfurt am Main

Das ist mir klar, das ist genau das, wovon wir ja reden... mit einer schleife, die dann einfach abgebrochen werden kann, wenn sich die dazugehörige variable ändert...

Nun ja, dann hat sich das wohl erledigt... Trotzdem danke für die Ratschläge :-)

Grüße Markus :)
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Denk daran, dass du die Variable mit einem Lock (s. z.B. threading.RLock) versehen musst.
Markus12
User
Beiträge: 195
Registriert: Dienstag 6. März 2007, 19:32
Wohnort: Frankfurt am Main

Warum muss ich einen Lock verwenden? Klappt auch ohne...?
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Wenn du aus mehreren Threads auf eine Variable zugreifst, MUSST du diese mit einem Lock sichern.
Probleme, wenn du das nicht machst, treten nur nicht deterministisch auf.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Wenn du nur ein Event setzt oder ein Flag auf True setzt, brauchst du keineswegs ein Lock.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Markus12
User
Beiträge: 195
Registriert: Dienstag 6. März 2007, 19:32
Wohnort: Frankfurt am Main

Ich habe nur einen Tread, warum ich mir dachte, dass ich da keinen Lock brauche... Werde mich da noch weiter einarbeiten müssen in Threads, die sind kompliziert und ist viel Material...
Danke an alle!

Grüße Markus :)
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Markus12 hat geschrieben:Ich habe nur einen Tread, warum ich mir dachte, dass ich da keinen Lock brauche...
Wenn du einen Thread startest, hast du den gestarteten Thread und den Main-Thread. Das macht zwei. Willst du jetzt mit beiden auf eine Variable zugreifen, musst du diese mit einem Lock schützen.

Wenn du das mit Events realisierst brauchst du natürlich keinen.

BTW:
@birkenfeld
Mit ``Event setzen`` und ``Flag auf True`` setzen, meinst du da das gleiche? Oder gibt es eine Alternative zum Event?
BlackJack

@ice2k3: So etwas wie ``thread.flag = True`` muss man nicht mit einem `Lock` schützen.
Antworten