Variable aus laufendem Thread auslesen

Code-Stücke können hier veröffentlicht werden.
Antworten
Helpless
User
Beiträge: 7
Registriert: Donnerstag 5. Februar 2009, 12:09

Beschäftige mich erst seit kurzem mit Python und bin dementsprechend noch ziemlich unerfahren. Jetzt stehe ich vor folgendem Problem: Ich soll, im Rahmen meines Praktikums, eine Ampelsimulation programmieren. Die Schaltung der Ampel erfolgt innerhalb eines Threads. Es soll zeitgleich eine Abfrage der aktuell geschalteten Phase und des dazugehörigen Schaltintervalls möglich sein. Da eine Returnanweisung den Thread beendet, suche ich nach einer anderen Möglichkeit, die aktuelle Phase zurückzugeben und diese für andere Funktionen abrufbar zu machen. Vielleicht kann mir da ja jemand einen Tipp geben, denn auch Google hat mir bisher noch keine Alternative aufgezeigt (vielleicht suche ich auch nach den falschen Begriffen). Hier mein bisheriger Code:

Code: Alles auswählen

from time import * 
import thread
import threading 
import os
import sys, traceback

class AsyncAmpel(threading.Thread):
    def __init__(self,ampel_p):
	"""Initialisierung der Klasse"""
	threading.Thread.__init__(self)
        self.ampel = ampel_p 

class Ampel(threading.Thread):

	l_Zustandsfolge_c=['rot','gelb','gruen','gelb']
	d_Eingaben_c={'i':'self.setIntervall()', 'e':'print self.getInfo(self.i_ndex_i)','b':'os._exit(0)','t':'print time()'}

	def __init__(self):
		"""Initialisierung der Klasse"""
		self.current_state = 'ausgeschaltet'
		self.ld_Zustandsuebergaenge_i={'rot':5,'gelb':3,'gruen':5,'ausgeschaltet':0}
		threading.Thread.__init__(self)
		self.i_ndex_i = 0


	def run(self):
		sleep(5)
		self.autoSchaltung()

	def eingabeAuswahl(self):
		"""Auswahl der Optionen"""
		while 1:
			print "Moechten Sie den Zustand der Ampel (e)rfragen, das Programm"
			print "(b)eenden oder einen Schalt(i)ntervall veraendern? "
			Eingabe = raw_input(">> ")
			try:
			  exec (self.d_Eingaben_c[Eingabe])
			except:
                           traceback.print_exc()
                           print 'Got', sys.exc_type, sys.exc_value

	def getInfo(self,i_ndex_i):
		"""Fragt den aktuellen Zustand der Ampel ab"""
		return self.l_Zustandsfolge_c[self.i_ndex_i], self.ld_Zustandsuebergaenge_i[self.l_Zustandsfolge_c[self.i_ndex_i]]
	
	def setIntervall(self):
		"""Aendert die Schaltintervalle"""
		Zustand_neu = raw_input("Welchen Zustand moechten Sie aendern? ")
		Intervall_neu = input("Neuer Intervall: ")
		self.ld_Zustandsuebergaenge_i[Zustand_neu] = Intervall_neu
		
	def autoSchaltung(self):
		"""Schaltet die Zustaende der Ampel automatisch"""
		self.i_ndex_i
		while 1:
			for self.i_ndex_i in range(len(self.l_Zustandsfolge_c)):
				start_time = time()
				print strftime("%H:%M:%S")
				state = self.l_Zustandsfolge_c[self.i_ndex_i]
				Intervall = self.ld_Zustandsuebergaenge_i[state]
				actual_time = time()
				print
				print "Die Ampel befindet sich im %sen Zustand" %self.l_Zustandsfolge_c[self.i_ndex_i]
				print "Die Schaltung erfolgt nach %d Sekunden" %Intervall
				print
				while actual_time - start_time <= Intervall:
					sleep(0.01)
					actual_time = time()
				self.i_ndex_i = self.i_ndex_i + 1
			
meineAmpel=Ampel()
runningAmpel=Ampel()
runningAmpel.start()
meineAmpel.eingabeAuswahl()
Vielen Dank für eure Hilfe...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hallo Helpless, willkommen im Forum,

Du solltest dringend mal PEP8 lesen und anwenden. Ansonsten: Schreib das ergebnis doch in eine Instanzvariable des Threads. So kann die auch von anderen Threads gelesen werden (und evtl. solltest du auf Locking achten).
Helpless
User
Beiträge: 7
Registriert: Donnerstag 5. Februar 2009, 12:09

Hallo Leonidas,
danke für deine schnelle Antwort. Ich weiss, ich habe nicht grade einen sauberen Programmierstil, daran muss ich wirklich noch arbeiten...
Ansonsten: Schreib das ergebnis doch in eine Instanzvariable des Threads.
Wie meinst du das? Mit Return zur Änderung der Instanzvariablen? Das würde ja den Durchlauf der Schleife beenden. Dachte ja durch

Code: Alles auswählen

self.i_ndex_i = self.i_ndex_i + 1
die Instanzvariable ändern zu können, was aber so wohl offensichtlich nicht funktioniert. Muss ich dem vielleicht noch irgendetwas voranstellen? Oder steh ich grad einfach nur auf dem Schlauch?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Helpless hat geschrieben:Dachte ja durch

Code: Alles auswählen

self.i_ndex_i = self.i_ndex_i + 1
die Instanzvariable ändern zu können, was aber so wohl offensichtlich nicht funktioniert. Muss ich dem vielleicht noch irgendetwas voranstellen? Oder steh ich grad einfach nur auf dem Schlauch?
Doch, das funktioniert durchaus so. Und wenn du nicht ``return``st, dann wird auch die Schleife nicht abgebrochen.
Helpless
User
Beiträge: 7
Registriert: Donnerstag 5. Februar 2009, 12:09

Leider scheint es doch nicht so zu funktionieren.
Die Ampel befindet sich im roten Zustand
Die Schaltung erfolgt nach 5 Sekunden

14:25:47

Die Ampel befindet sich im gelben Zustand
Die Schaltung erfolgt nach 3 Sekunden

e
('rot', 5)
Moechten Sie den Zustand der Ampel (e)rfragen, das Programm
(b)eenden oder einen Schalt(i)ntervall veraendern?
>> 14:25:51

Die Ampel befindet sich im gruenen Zustand
Die Schaltung erfolgt nach 5 Sekunden

e
('rot', 5)
Moechten Sie den Zustand der Ampel (e)rfragen, das Programm
(b)eenden oder einen Schalt(i)ntervall veraendern?
>> e
('rot', 5)
Also egal in welcher Phase die Ampel sich befindet, die Abfrage ergibt immer "rot". Hast du eine Idee, woran das liegt? Habe ich vielleicht in der Abfragefunktion nen Fehler?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Oh, Java, C und ein "exec"^^

Du musst natürlich auch die richtige Ampel befragen:

Code: Alles auswählen

runningAmpel=Ampel() 
runningAmpel.start() 
runningAmpel.eingabeAuswahl()
Zu dem gruseligen Code wird sich bestimmt noch jemand genauer äußern, da habe ich gerade keine lust zu.

Sebastian
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

statt exec:

Code: Alles auswählen

import threading
import traceback


class Ampel(threading.Thread):

    def _printInfo(self):
        print self.getInfo(self.i_ndex_i)

    def _quit(self):
        os._exit(0)

    def _printTime(self):
        print time()
    
    d_Eingaben_c={'e':_printInfo,'b':_quit,'t':_printTime}

    def eingabeAuswahl(self):
        """Auswahl der Optionen"""
        while 1:
            print "Moechten Sie den Zustand der Ampel (e)rfragen, das Programm"
            print "(b)eenden oder einen Schalt(i)ntervall veraendern? "
            Eingabe = raw_input(">> ")
            try:
              self.d_Eingaben_c[Eingabe](self)
            except:
              traceback.print_exc()
              print 'Got', sys.exc_type, sys.exc_value 
oder so, dann kann man auch Methoden überschreiben:

Code: Alles auswählen

ort threading
import traceback


class Ampel(threading.Thread):

    def _printInfo(self):
        print self.getInfo(self.i_ndex_i)

    def _quit(self):
        os._exit(0)

    def _printTime(self):
        print time()
    
    d_Eingaben_c={'e':'_printInfo','b':'_quit','t':'_printTime'}

    def eingabeAuswahl(self):
        """Auswahl der Optionen"""
        while 1:
            print "Moechten Sie den Zustand der Ampel (e)rfragen, das Programm"
            print "(b)eenden oder einen Schalt(i)ntervall veraendern? "
            Eingabe = raw_input(">> ")
            try:
              getattr(self, self.d_Eingaben_c[Eingabe])()
            except:
              traceback.print_exc()
              print 'Got', sys.exc_type, sys.exc_value 
 
Helpless
User
Beiträge: 7
Registriert: Donnerstag 5. Februar 2009, 12:09

Oh, das erklärt natürlich einiges :oops: (wie konnt ich das denn übersehn?!?)

Dankeschön, jetzt läuft alles wie´s soll...

Wünsch euch beiden noch nen schönen Tag
Antworten