[python 2.7] Thread is gestopt maar volgens python niet

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Yoram
  • Registratie: Augustus 2004
  • Laatst online: 05-08 14:22
Hallo,

Zojuist heb ik een raar probleem in python waar ik niet uitkom. Ik ben bezig met een script die een foto
maakt en hem download en dan te zien is op m'n scherm.
Ik start een thread vanuit een functie die luistert naar een knop aan een GPIO poort.

Python:
1
2
3
4
5
6
7
8
9
10
#de initialisatie van de thread:
takepic_h = take_picture()
th_takepic = threading.Thread(target=takepic_h.run, name="take_picture thread")
th_takepic.daemon = False

#in de functie word deze getrigger met
if not th_takepic.isAlive():
    th_takepic.start()
else:
    print( "server> Warning: Er word al een foto gemaakt")


De take_picture functie bestaat uit een aantal commando's die naar een websocket(met Tornado) worden gestuurd. Daartussen zitten wat "time.sleep(x)" regels. En verder gebeurt er niks bijzonders in de functie.

Als ik deze de eerste keer trigger is er niks aan de hand. De functie doet z'n ding zonder fouten o.i.d. Bij de 2e keer krijg ik de foutmelding: RuntimeError: threads can only be started once

Dat is raar, want als ik check met "th_takepic.isAlive()" krijg ik een "False". Dus je zou zeggen dat de thread klaar is. Zelfs als ik de take_picture functie helemaal leegmaak doet tie het zelfde. Dus ik weet zeker dat het daar niet aan ligt. Ook als ik "threading.enumerate()" doe in een for loop staat de thread er niet tussen.

Waar zou dit aan kunnen liggen? Ik post geen hele lap code omdat dat natuurlijk niet de bedoeling is, ik hoop daarom dat er een soort van algemeen antwoord is.

offtopic:
Disclaimer: Ik speel al even met python voor verschillende hobby projecten en heb mijn kennis alleen van het web, dus ben geen python pro ;)

Hallo!


Acties:
  • 0 Henk 'm!

  • BasilFX
  • Registratie: Mei 2004
  • Laatst online: 11-09 08:28

BasilFX

BasilFX

Je kunt een thread niet hergebruiken: voor een tweede keer dien je opnieuw een Thread te initialiseren.

Volgens de docs is is_alive() alleen True "just before the run() method starts until just after the run() method terminates". Dit klopt dus met wat je controleert, maar het geeft dus niet aan dat je 'm opnieuw kan gebruiken :)

Even voor de zekerheid: th_takepic.daemon = False is niet nodig want elke Thread die aangemaakt wordt is standaard geen daemon thread. Als je dat wel wilt, dan worden alle threads beëindigd als je applicatie stop.

http://www.basilfx.net


Acties:
  • 0 Henk 'm!

  • Yoram
  • Registratie: Augustus 2004
  • Laatst online: 05-08 14:22
Aaah, meen je dat? Aangezien ik een hele avond er aan heb verspeelt :p. Thx voor je antwoord btw!
Is het dan wel zo dat als een thread klaar is en opnieuw opnieuw word geïnitialiseerd, er niks meer overblijft van de oude thread in het geheugen o.i.d? Wat de take_picture functie is iets wat wel een stuk of 100 keer per dag gecalled gaat worden.

[ Voor 3% gewijzigd door Yoram op 01-08-2016 13:56 ]

Hallo!


Acties:
  • +1 Henk 'm!

  • BasilFX
  • Registratie: Mei 2004
  • Laatst online: 11-09 08:28

BasilFX

BasilFX

Yoram schreef op maandag 01 augustus 2016 @ 13:56:
Aaah, meen je dat? Aangezien ik een hele avond er aan heb verspeelt :p. Thx voor je antwoord btw!
Is het dan wel zo dat als een thread klaar is en opnieuw opnieuw word geïnitialiseerd, er niks meer overblijft van de oude thread in het geheugen o.i.d? Wat de take_picture functie is iets wat wel een stuk of 100 keer per dag gecalled gaat worden.
Je kunt nog wel bij die thread, maar opnieuw starten kan niet meer.

Wellicht ben je dan op zoek naar een andere opzet. Even uit de losse pols:

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import threading
import time

class Worker(threading.Thread):
    def __init__(self):
        super(Worker, self).__init__()

        # Dit is een object om te synchroniseren. Ideaal gezien is er geen
        # communicatie tussen deze class en de 'buitenwereld' behalve dit
        # door middel van dit object, om race conditions te voorkomen.
        self.event = threading.Event()

    def run(self):
        while True:
            # Deze call blocked tot dat event ge-set is.
            self.event.wait()

            # Doe wat werk.
            print "Bezig"
            time.sleep(10)
            print "Klaar"

            # Werk is klaar, ga terug wachten tot we weer mogen.
            self.event.clear()

worker = Worker()

worker.daemon = True
worker.start()

# Check of bezig is.
print worker.event.is_set()

# Doe wat werk.
worker.event.set()

# Blijf checken of ie bezig is.
for i in range(11):
    time.sleep(1)
    print worker.event.is_set()


Nu blijf je een thread behouden, die je met een Event triggered om werkt te doen.

[ Voor 10% gewijzigd door BasilFX op 01-08-2016 15:02 ]

http://www.basilfx.net