Thread pausieren / neustarten?

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
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

Hallo,

kurze Frage:
Kann man Thread pausieren oder neustarten?

Zum Programmstart wird der Thread gestartet und das Hauptprogramm läuft wunderbar weiter. Nachdem stoppen möchte ich den Thread wieder neustarten, leider hält dies das Hauptprogramm an.

Mein Versuch war:

Code: Alles auswählen


#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import threading
import time


class Loop(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.count = 0
        # Values for self.running:
        # 0 : Ready.
        # 1 : Running.
        # 2 : Finished.
        self.running = 0

    def run(self):
        self.running = 1
        self.loop()

    def loop(self):
        pass
        print 'loop'
        time.sleep(0.1)
        if not self.running == 2:
            self.loop()

    
class Application:
    def __init__(self):
        print "Create and start counter"         
        loop = Loop()
        loop.start()
        print "Main-Programm don´t need to wait"   
        time.sleep(1)
        print "Main-Programm is still running - great"
        time.sleep(1) 
        print "Stop counter"
        loop.running = 2
        time.sleep(1)
        print "Start counter again"
        loop.run()         # <--------------------------- break ;(
        print "Main-Programm should´t wait" 
        loop.running = 2  
        print "Main-Program finished."
        
        
if __name__ == "__main__":
   app = Application()
Bei loop.start() statt loop.run kommt: AssertionError: thread already started
loop.

Bei loop.stop() statt loop.run kommt: AttributeError: 'Loop' object has no attribute 'stop'

Nur loop.running = 1 auszuführen bringt nix, da der loop nicht ausgeführt wird. Und mit zusätzlich loop.loop() passiert logischerweise das gleich wie mit loop.run()

hmm.

Ich freue mich sehr über Tipps und Hilfe!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Du musst ne neue Instanz von Loop erstellen, weil man den gleichen Thread nicht zweimal starten kann.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo,

du solltest vielleicht weniger durch ausprobieren programmieren, sondern durch Dokumentation lesen ;-) "start" ist nicht dafür gedacht, dass es mehrfach aufgerufen wird. Wenn du die "run"-Methode hingegen direkt aufrufst, dann wird der Thread nicht verwendet, sondern die Methode ganz normal ausgeführt. Die ganzen "sleep"s sehen auch nicht unbedingt vertrauenswürdig aus. Auch ist es nicht unbedingt zu empfehlen, aus "loop" noch einmal "loop" aufzurufen. Da wirst du ganz schnell ans ende des Rekursionslimits stoßen.

Und hiermit kannst du dein Problem lösen.

Edit:

Code: Alles auswählen

def run(self);
    while True:
        self.lock.acquire();
        #your code here
        self.lock.release()
    
def suspend(self):
    self.lock.acquire();

def restart(self):
    self.lock.release()
Das Leben ist wie ein Tennisball.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

``restart`` ist in diesem Fall kein geeigneter Bezeichner. Etwas wie ``continue`` wäre besser.
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

super, werde ich gleich "ausprobieren ;)"

ja, ich merke auch das Api lesen doch sehr nützlich ist,
ich bin auch immer öfter auf der Seite, nur ist es leider
anfangs immer etwas schwer das zu verstehen.

Ich bedanke mich vielmals !!!
Python bring wirklich viel Spaß ;)

PS: Die sleeps und so habe ich nur für das Beispiel benutzt, um mein Problem zu verdeutlichen, will euch ja nicht noch mehr als nötig auf erlegen.

Also nochmal Danke und gleich mal testen!
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Eventuell beschreibst du uns auch mal dein gesamtes Problem, ich habe irgendwie das Gefühl, dass man da noch einiges optimieren kann.
(s. auch XY-Problem)
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

Naja,

das Problem ist, dass ich ein Objekt haben möchte, dass mir Sachen zu einer bestimmten Zeit anzeigt, dass die Zeit um is. (Eventmäßig)

Im Hauptprogramm soll nix stehen bleiben, wenn ich etwas starte oder neustarte. Hier arbeite ich mit mit einer main.update funktion und mit time.sleep(0.01) in einer while-schleife...

Code: Alles auswählen

....
while main.isActive():
  main.update()
  time.sleep(0.01)
....
Wenn nun zum Bespiel etwas nach 1 Sekunde erscheinen soll, dann wollte ich das Objekt starten und in dem Objekt time.sleep(1) nutzen. Das Objekt kann auch verschwinden und von alleine nach 1 Sek. wieder erscheinen...

Optimieren kann man glaube ich noch ganz viel, aber erstmal bin ich froh, wenn es überhaupt läuft. Falls du oder jemand wirklich Lust und Zeit hat mir zu helfen... ich bin in Hamburg.

Nun mach ich erstmal weiter. Bis gleich.
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

Ich hab jetzt den Codebestandteil von EyDu in mein Beispiel eingebaut.

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import threading
import time


class Loop(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        print 'Start'

    def run(self):
        while True:
            self.lock.acquire(); # <--------------------------- 
            print 'code'
            self.lock.release()
           
    def suspend(self):
        self.lock.acquire();
    
    def restart(self):
        self.lock.release()
    

    
class Application:
    def __init__(self):
        print "Create and start counter"         
        loop = Loop()
        loop.start() # <--------------------------
        print "Main-Programm don´t need to wait"   
        time.sleep(1)
        print "Main-Programm is still running - great"
        time.sleep(1) 
        print "Stop counter"
        loop.suspend()
        time.sleep(1)
        print "Start counter again"
        loop.restart()     
        time.sleep(2)
        print "Main-Programm should´t wait" 
        loop.suspend()
        print "Main-Program finished."
        
        
        
        
if __name__ == "__main__":
   app = Application()

Nur leider kennt loop lock nicht.
self.lock.acquire(); AttributeError: 'Loop' object has no attribute 'lock'
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

mayx hat geschrieben:Nur leider kennt loop lock nicht.
self.lock.acquire(); AttributeError: 'Loop' object has no attribute 'lock'
Weil du ja kein Lock-Objekt erstellt hast.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

Sind Lock-Objekte spezielle Objekte oder meinst du den Namen der Klasse?

Wahrscheinlich muß in die Zeile noch das Lock-Objekt, oder?

Code: Alles auswählen

def __init__(self):
        threading.Thread.__init__(self)
        print 'Start'
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Also EyDu hat dir doch die Dokumentation zu ``threading.Lock()`` verlinkt. Eine Instanz davon zu erstellen und diese an ``self.lock`` zu binden wirst du wohl alleine schaffen, oder?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

tut mir leid dich möglicherweise zu nerven, aber threads sind finde ich nicht ganz so einfach zu verstehen.
Danke für den Tipp. Bin auch einwenig überarbeitet....

Code: Alles auswählen

class Loop(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.lock = threading.Lock()
        print 'Start'

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import threading
import time


class Loop(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.lock = threading.Lock()
        print 'Start'

    def run(self):
        while True:
            self.lock.acquire();
            print 'code'
            time.sleep(1) # <--------------------------------
            self.lock.release()
           
    def suspend(self):
        self.lock.acquire();
    
    def restart(self):
        self.lock.release()
    

    
class Application:
    def __init__(self):
        print "Create and start counter"         
        loop = Loop()
        loop.start()
        time.sleep(2)
        print "Stop counter"
        loop.suspend()
        time.sleep(2)
        print "Start counter again"
        loop.restart()     
        time.sleep(2)
        print "Stop counter"
        loop.suspend()
        print "Main-Program finished."
        
        
        
        
if __name__ == "__main__":
   app = Application()
Blöderweise hält der Counter nicht an, wenn ich time.sleep(1) bei Code einfüge.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Ich bin jetzt bei deiner Beschreibung nicht komplett durchgestiegen, aber eventuell ist ein "Timer" (http://docs.python.org/library/threadin ... er-objects) genau das Richtige!
(Du kannst einen Timer auch wieder abbrechen)
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

interessant!

Ich versuch mich nochmal komplett ohne Code:
Es gibt Objekte, die erscheinen und verschwinden.
Stell dir vor, es spielt Musik und jeden Takt soll etwas passieren.

- 1 Sekunde / Event / es passiert was
warten.... nix
- 1 Skunde / Event / es passiert was
warten... nix
(immer und immer wieder)

Dies ist aber nur nebensächlich, wie zum Beispiel ein Email-Abruf-Funktion alle 5 Min.. Wäre dessen kann man ja auch Emails schreiben oder andere Angaben machen.

Dies funktioniert auch wunderbar mit dem Thread.

Nun möchte ich einen Funktion hinzufügen, dass die Musik neustartet und den Thread / Timer oder ähnliches wieder auf null setzt und passend beginnt. (synchron)
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Dann kannst du gut einen Timer verwenden. In der Funktion, die du dem Timer übergibst, startest du den Timer einfach neu.
> Das sind dann deine 1-Sek. Intervalle von deinem Bsp

In der 2. Funktion setzt du den Timer einfach zurück und startest ihn neu.
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

Cool, es läuft ;)

Leider steht in der Api:
"The interval the timer will wait before executing its action may not be exactly the same as the interval specified by the user."

Welche ist denn die genauste Möglichkeit Zeitintervalle abzugeben?

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import threading
import time

class Loop(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        print 'Start Init'
        self.waitTime = 1
        self.t = threading.Timer(self.waitTime, self.loopIt)
   
    def start(self):
        print 'Start Code'
        self.t.start() 
        
    def startItAgain(self):
        print 'Start startItAgain'
        self.t = threading.Timer(self.waitTime, self.loopIt)
        self.t.start()     
    
    def loopIt(self):
        print 'loopIt'
        self.t = threading.Timer(self.waitTime, self.loopIt)
        self.t.start() 
        
    def stopIt(self):
        print 'stopIt'
        self.t.cancel()

    
class Application:
    def __init__(self):
        print "Main- Create and start counter"         
        loop = Loop()
        loop.start()
        time.sleep(5)
        print "Main - Stop counter"
        loop.stopIt()
        print "Main - Still running 1"
        print "Main - Still running 2"
        time.sleep(5)
        print "Main - Start counter again"
        loop.startItAgain()     
        time.sleep(5)
        print "Stop counter"
        loop.stopIt()
        print "Main - Program finished."
        
        
if __name__ == "__main__":
   app = Application()
oder:

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import threading
import time


class Loop(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.count = 0
        # Values for self.running:
        # 0 : Ready.
        # 1 : Running.
        # 2 : Finished.
        self.running = 0

    def run(self):
        self.running = 1
        self.loop()

    def loop(self):
        pass
        print 'loop'
        time.sleep(0.1)
        if not self.running == 2:
            self.loop()

    
class Application:
    def __init__(self):
        print "Create and start counter"         
        loop = Loop()
        loop.start()
        print "Main-Programm don«t need to wait"   
        time.sleep(1)
        print "Main-Programm is still running - great"
        time.sleep(1) 
        print "Stop counter"
        loop.running = 2
        time.sleep(1)
        print "Start counter again"
     #   del loop
        loop = Loop()
        loop.start()
        time.sleep(2)
        print "Main-Programm should«t wait" 
        loop.running = 2  
        print "Main-Program finished."



Vielen Dank euch Alle!
alpha
User
Beiträge: 195
Registriert: Freitag 23. Mai 2003, 23:24
Wohnort: Ulm

Hallo Mayx,

es funktioniert vielleicht, aber meiner Meinung nach nicht sehr lange!

Du rufst loop mit self.loop rekursiv auf, dabei wird loop aber nie fertig.
Ich denke irgendwann bekomst nen Stackoverflow.

Bitte schau Dir http://www.python-forum.de/topic-3869.html
an.. Da zeigt dir Gerold wie man es richtig macht :D

Grüße
alpha
mayx
User
Beiträge: 71
Registriert: Sonntag 3. Mai 2009, 02:51

ah, super.
danke.
Antworten