Seite 1 von 1
Steuerungs-Skript
Verfasst: Donnerstag 17. Juli 2014, 13:49
von mobby
Hey liebe Python Community,
folgendes Problem bzw. Situation, ich möchte mit einem Steuerungs-Skript einige Aufgaben erledigen. Im Folgenden die Aufgaben:
1. Das Skript startet und geht davon aus, dass noch kein Zähler läuft (das ist gewollt so), also haben wir eine Liste, in der die Stati der Zähler enthalten sind, 8 Zähler gesamt.
2. Der Initiations-Prozess beginnt, bedeutet, dass als erstes eine Konfigurationsdatei gelesen wird, in der drin steht, ob ein Zähler aktiviert wurde oder nicht.
3. Erste Abfrage besteht daraus, zu überprüfen ob Zähler x schon aktivert wurde, ist dies der Fall (kann beim ersten Start nicht sein), wird der aktuelle For-Schleifen Durchlauf übersprungen.
4. Als nächstes wird überprüft, ob der Zähler x aktiviert wurde. Ist dies der Fall, soll ein Thread mit dem entsprechenden Skript starten ( dazu später mehr). Und anschließend der Status des Zählers x auf "1" also ON gestellt werden.
5. Als nächste Abfrage wird überprüft, ob der Zähler deaktiviert wurde, aber der Thread noch läuft. Ist dies der Fall, soll der Thread gestoppt werden und der Status wieder auf "0" OFF gestellt werden.
6. Falls nichts der Fall sein sollte, wird der nächste Zähler überprüft.
7. Am ende soll die Status-Liste der Zähler übergeben werden, also im nächsten Durchlauf den gleichen Inhalt haben, dabei bin ich mir nicht sicher, ob ich das so richtig gemacht habe.
Zum Thema Threads ... keine Ahnung ob das so richtig ist wie ich den Thread zu stoppen versuche, ich gehe mal davon aus, dass es nicht stimmt. Bin aber irgendwie net so ganz schlau aus der Doku geworden, da bräuchte ich noch etwas Hilfe.
Neben den Thread Themen eine allgemeine Frage an alle, ob das sonst passt, also die Vorgehensweise, oder ob man was ganz anders gestalten sollte? Danke für Feedback!
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import read_ec as ec
import read_s0 as s0
import config_datei as cod
from time import sleep
from threading import Lock
from threading import Thread
def read_config_status():
if is_changed(config_datei):
config_datei = reload(config_datei)
return cod.config["counterStates"]
def start_s0(x):
number = x + 1
intervall = 900
frequency = 100
digital_input = x
led_output = x
table_name = "S0_Zaehler_0" + number
s0.main(intervall, frequency, table_name, digital_input, led_output)
def set_on(counter_status, x):
counter_status[x] = 1
return counter_status
def set_off(counter_status, x):
counter_status[x] = 0
return counter_status
def initiation_process(counter_status):
config_status = read_config_status()
for x in range(8):
if counter_status[x] = 1:
break
elif config_status[x] = "active":
start_s0_thread(x)
set_on(counter_status, x)
break
elif config_status[x] = "inactive" and counter_status[x] = 1:
stop_s0_thread(x) #der jeweilige thread soll beendet werden
set_off(counter_status, x)
break
else:
continue
return counter_status #soll die Liste mit den Stati weiterschleifen
def start_s0_thread(x):
thread = Thread(target=start_s0, name=x args=(number))
thread.setDaemon(True)
thread.start
def stop_s0_thread(x): #keine Ahnung ob das so richtig ist ...
thread = Thread(name=x) #soll den Thread mit dem namen x stoppen ... ?!
thread.stop
def main():
counter_status = [
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
]
while True:
initiation_process(counter_status)
sleep(60)
if __name__ == '__main__':
main()
Re: Steuerungs-Skript
Verfasst: Donnerstag 17. Juli 2014, 14:37
von BlackJack
@mobby: Das ist eine Menge Code dafür das der *einige* Syntaxfehler enthält. Das ist also nichts was Du mal laufen lassen hast. Vergleiche werden mit ``==`` und nicht mit ``=`` gemacht, und Argumente werden durch ``,`` und nicht durch Leerzeichen getrennt.
`config_datei` wird benutzt bevor es definiert wird, letztendlich ist der Name ja aber sowieso `cod`, wobei `config_datei` wesentlich deutlicher ist. Abkürzungen sollte man vermeiden wenn sie das Programm schwerer zu verstehen machen. In einem Modul das als Konfiguration verwendet wird, würde ich die Daten auf Modulebene erwarten und nicht noch einmal eine Ebene weiter in ein Wörterbuch mit dem Namen `config` verschoben.
Die `is_changed()`-Funktion ist nicht definiert.
Der Code ist sich nicht darüber einig was für Werte `counter_status` haben kann. 0, 1, '0'? Vielleicht auch '1'? Die Zahlen 0 und 1 sind nicht das gleiche wie Zeichenketten mit der Ziffer 0 oder 1. Und an der Stelle hätte man vielleicht auch `True` und `False` gewählt um klar zu machen, dass es keine 2 geben kann.
`set_on()` und `set_off()` sind fast identisch, da würde sich wohl eher eine `set_counter_state()`-Funktion anbieten die den Status als Argument bekommt. Da der Rückgabewert nicht nur unnötig, sondern auch sehr unschön ist, fragt sich ob man hier überhaupt eine Funktion für braucht. Die API ist unschön weil das übergebene Argument verändert *und* zurückgegeben wird. Der Aufrufer hat diesen Wert doch aber schon, sonst hätte er ihn nicht übergeben können.
Das gleiche gilt für `initiation_process()`. Das was der Kommentar am Ende suggeriert ist nicht schön. Was man machen kann, und was in Python auch üblicher wäre, ist hier eine *neue* Liste zu erstellen und die dann zurück zu geben. Dann wird man auch den `x`-Index los. Der zusätzlich noch das unschönde Problem hat, dass dort die 8 hart ins Programm kodiert ist, statt sich an der Länge der Konfiguration für die Counter zu orientieren.
Die Logik in der Schleife funktioniert nicht. Man kann einen Counter nicht stoppen, denn wen er läuft, dann wird nichts weiter geprüft. Ich denke auch das die ganzen ``break``\s da falsch sind. Die verlassen die *Schleife*.
Threads werden nicht gestartet, weil die `start()`-Methode nicht *aufgerufen* wird.
Und nein, so kann man Threads nicht stoppen. Du merkst Dir die gestarteten Thread-Objekte nirgends, also kannst Du darauf keinen Einfluss mehr nehmen. Man kann über eine ensprechende Funktion zwar über alle Threads iterieren, aber eigentlich möchte man sie sich selbst in einer geeigneten Datenstruktur merken. Also zum Beispiel das der `counter_status` nicht 0 oder 1 enthält sondern `None` oder ein `Thread`-Objekt. Das nächste ist, dass man Threads nicht von aussen stoppen kann. Die müssen eine Möglichkeit bieten das man ihnen mitteilt, dass sie sich selber beenden sollen, und das müssen sie dann auch tun.
Re: Steuerungs-Skript
Verfasst: Donnerstag 17. Juli 2014, 14:58
von mobby
@BlackJack: Vielen lieben Dank für das ausführliche Feedback. Ich muss gestehen, dass ich den Code wirklich kein einziges Mal ausprobiert hatte, wird nicht mehr vorkommen. Ich versuche die angesprochenen Punkte umzusetzen und werde mich zurückmelden, sobald ich weiter bin.

Re: Steuerungs-Skript
Verfasst: Sonntag 20. Juli 2014, 22:19
von mobby
Die `is_changed()`-Funktion ist nicht definiert.
Habe ich *vercheckt*, Modul wird jetzt einfach vor jedem Lesen neu geladen. Außerdem habe ich das mit den Bibliotheken bzw. Listen auf Moduleben erst mal noch belassen. Funktioniert soweit ja auf jeden Fall und es gibt Dinge mit höherer Priorität in diesem Projekt.
Code: Alles auswählen
def read_config_status():
config_datei = reload(config_datei)
return config_datei.counterStates
Der Code ist sich nicht darüber einig was für Werte `counter_status` haben kann. 0, 1, '0'? Vielleicht auch '1'? Die Zahlen 0 und 1 sind nicht das gleiche wie Zeichenketten mit der Ziffer 0 oder 1. Und an der Stelle hätte man vielleicht auch `True` und `False` gewählt um klar zu machen, dass es keine 2 geben kann.
Hab ich abgeändert, klingt sehr sinnvoll

.
`set_on()` und `set_off()` sind fast identisch, da würde sich wohl eher eine `set_counter_state()`-Funktion anbieten die den Status als Argument bekommt. Da der Rückgabewert nicht nur unnötig, sondern auch sehr unschön ist, fragt sich ob man hier überhaupt eine Funktion für braucht. Die API ist unschön weil das übergebene Argument verändert *und* zurückgegeben wird. Der Aufrufer hat diesen Wert doch aber schon, sonst hätte er ihn nicht übergeben können.
Habe ich ganz rausgenommen, Status wird jetzt direkt über die Liste ersetzt.
Das gleiche gilt für `initiation_process()`. Das was der Kommentar am Ende suggeriert ist nicht schön. Was man machen kann, und was in Python auch üblicher wäre, ist hier eine *neue* Liste zu erstellen und die dann zurück zu geben. Dann wird man auch den `x`-Index los. Der zusätzlich noch das unschönde Problem hat, dass dort die 8 hart ins Programm kodiert ist, statt sich an der Länge der Konfiguration für die Counter zu orientieren.
Das mit der Länge der Konfiguration kann man einfügen, habe ich jetzt aber erst mal gelassen. Das mit der neuen Liste verstehe ich nicht ganz, wie soll ich das verstehen?
Die Logik in der Schleife funktioniert nicht. Man kann einen Counter nicht stoppen, denn wen er läuft, dann wird nichts weiter geprüft. Ich denke auch das die ganzen ``break``\s da falsch sind. Die verlassen die *Schleife*.
Breaks sind raus und auch die Logik etwas angepasst. Allerdings wie oben schon angedeutet, bin ich mir mit der Liste noch nicht ganz sicher, ob das so passt. Auch ist mir nicht klar, ob wenn ich mit return die Liste, unabhängig davon ob sie jetzt neu erstellt wurde oder die bestehende ist, zurückgegebe, die zurückgegeben beim erneuten while-Schleifen Durchlauf erkannt wird?
Code: Alles auswählen
def initiation_process(counter_status):
config_status = read_config_status()
for x in range(8):
if config_status[x] == "active" and counter_status[x] == True:
continue
elif config_status[x] == "active" and counter_status[x] == False:
start_s0_thread(x)
counter_status[x] = True
elif config_status[x] == "inactive" and counter_status[x] == True:
stop_s0_thread(x)
counter_status[x] = False
else:
continue
return counter_status
Code: Alles auswählen
def main():
counter_status = [
False,
False,
False,
False,
False,
False,
False,
False,
]
while True:
initiation_process(counter_status)
sleep(60)
Threads werden nicht gestartet, weil die `start()`-Methode nicht *aufgerufen* wird.
Und nein, so kann man Threads nicht stoppen. Du merkst Dir die gestarteten Thread-Objekte nirgends, also kannst Du darauf keinen Einfluss mehr nehmen. Man kann über eine ensprechende Funktion zwar über alle Threads iterieren, aber eigentlich möchte man sie sich selbst in einer geeigneten Datenstruktur merken. Also zum Beispiel das der `counter_status` nicht 0 oder 1 enthält sondern `None` oder ein `Thread`-Objekt. Das nächste ist, dass man Threads nicht von aussen stoppen kann. Die müssen eine Möglichkeit bieten das man ihnen mitteilt, dass sie sich selber beenden sollen, und das müssen sie dann auch tun.
Ich denk, dass das fast ein eigenes Thema ist, ich versuche erst mal alle anderen Punkte abzuarbeiten, um das als letztes zu realisieren.
Re: Steuerungs-Skript
Verfasst: Sonntag 20. Juli 2014, 23:27
von BlackJack
@mobby: Was meinst Du mit „erkannt”? Es wird eine Liste übergeben, das ist die *selbe* Liste die beim Aufrufer auch an den Namen `counter_status` gebunden ist. Wenn man da in der Liste Veränderungen vornimmt, dann ändert man *die* Liste.
Die Zweige mit dem ``continue`` sind überflüssig, denn das würde ohne diese Anweisung ja sowieso passieren.
Wenn man nicht diesen Status als indirektion verwenden würde sondern dort direkt Objekte speichert, die einen Thread/Counter repräsentieren oder `None` wenn der entsprechende Counter nicht läuft, dann liesse sich das ungefähr so schreiben:
Code: Alles auswählen
from itertools import izip, repeat
# ...
def initiation_process(counters):
result = list()
for counter_status, counter in izip(read_config_status(), counters):
if counters_status == 'active' and counter is None:
counter = start_s0_thread()
elif counter_status == 'inactive' and counter is not None:
stop_s0_thread(counter)
counter = None
result.append(counter)
return result
def main():
counters = repeat(None)
while True:
counters = initiation_process(counters)
sleep(60)
Wobei es vielleicht mehr Sinn machen würde mit Objekten zu starten welche die Zähler repräsentieren und die jeweils eine `start()`- und eine `stop()`-Methode besitzen und eine Möglichkeit zum testen ob sie gerade laufen. Also ein Attribut, ein Property, oder eine Methode.
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 10:50
von mobby
@BlackJack: Oha, jetzt wirds echt tricky ^^ Also ich glaube mit deinem Ansatz funktioniert meine Idee nicht, weil ich nicht nur eine absolute Anzahl an Zählern habe, sondern feste Nummern, also es kann die Situtaion auftreten, dass Zähler 1 und Zähler 5 gestartet sind und nicht nur absolut 2 Stück. Es muss also die Position in der Liste berücksichtigt werden. Ich habe mal einige Ansätze von dir übernommen und mit meinem Modell kombiniert. Diesmal auch getestet und funktioniert auch so, wie geplant:
Code: Alles auswählen
import config_datei
from time import sleep
def read_config_status():
reload(config_datei)
return config_datei.counterStates
def initiation_process(counters_status):
config_status = read_config_status()
for x in range(len(counters_status)):
if config_status[x] == "active" and counters_status[x] == False:
print "Nr " + str(x + 1) + " wird gestartet"
counters_status[x] = True
elif config_status[x] == "inactive" and counters_status[x] == True:
print "Nr " + str(x + 1) + " wird gestoppt"
counters_status[x] = False
return counters_status
def main():
counters_status = []
for x in range(len(read_config_status())):
counters_status.append(False)
while True:
counters_status = initiation_process(counters_status)
sleep(60)
if __name__ == '__main__':
main()
Die Print Befehle ersetzen das Starten der Threads, um erstmal die Funktion der Schleife zu prüfen. Jetzt muss ich nur ein Objekt für das Starten meiner Threads bauen, bei dem die absolute Nummer des Zählers mit übergeben wird, sowie dessen Status, um dem Thread intern zu übergeben, dass wenn sein Status auf False springt, er sich beenden soll. Ein Ansatz dafür wäre sehr hilfreich, allerdings versuch ichs auch gerne erst mal selbst.

Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 11:01
von BlackJack
mobby: Ja ich hatte da einen dummen Fehler in der Funktion. Jetzt sollte es funktionieren, weil die Liste mit immer für jeden Zähler einen Eintrag enthält.
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 11:24
von mobby
@BlackJack: Hm, ne irgendwie nicht. Bei deinem Code stelle ich fest, dass bei jedem Durchlauf die Zähler neu gestartet werden, aber das ist ja genau das, was ich verhindern will. Ist der Zähler einmal gestartet muss er nicht neu gestartet werden, sondern es soll nichts pasieren. Erst wenn der Status aus der config_datei sich ändert, soll etwas passieren, nämlich der Stopp des Zählers, bzw. eine Parameter-Übergabe an den jeweiligen Thread, dass er sich von selbst schließt. Außerdem habe ich so auch keine eindeutige Identifizierung des jeweiligen Zählers, also die Geschichte mit x passt in mein Konzept schon ganz gut, weil in dem zu startenden Thread brauch ich diesen Wert des Zählers.
Das versteh ich auch einfach nicht. Mir ist klar, dass ich beim Starten des Threads Argumente in Form eines Status übergeben kann. Intern im Thread kann ich dieses Argument überprüfen und sobald es sich ändert die Funktion, bzw. den Thread schließen. Nur jetzt die kritische Frage: Wie kann ich während der Thread bereits gestartet wurde, also im Nachhinein, den Parameter neu übergeben bzw. ihn ändern?
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 11:57
von BlackJack
@mobby: Das kann eigentlich nur passieren wenn `start_s0_thread()` den Wert `None` zurück gibt, und nicht irgendwas was den laufenden Zähler repräsentiert. Genau das wäre dann ja auch die eindeutige Identifikationsmöglichkeit.
Du musst Dir den Wert halt irgendwie merken. In meinem Ansatz wäre dass das was die `start_s0_thread()`-Funktion zurück gibt. Das muss ein Objekt sein, über das man mit dem Thread kommunizieren kann.
Ab ”schönsten” wäre es an der Stelle vielleicht wenn man einfach für jeden Zähler an der Stelle ein Objekt mit `start()`, `stop()` und `is_running` hat, über das man einen Zähler starten, stoppen, und den Zustand prüfen kann.
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 13:19
von mobby
@BlackJack: Okay, also ich habe jetzt mal was versucht ... ich bin mir zwar relativ sicher, dass es aus professioneller Sicht ziemlich katastrophal ist, aber für den Fall, dass es sich nur um einen Zähler handeln würde, funktioniert es. Jetzt meine Herausforderung, wie projeziere ich das mit dem Objekt auf mehrere Zähler?
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import config_datei
from time import sleep
from threading import Lock
from threading import Thread
def read_config_status():
reload(config_datei)
return config_datei.counterStates
def start_s0(x, status):
print "S0_Zaehler_0" + str(x + 1)
print status.get_status()
while True:
if status.get_status() == False:
break
sleep(5)
def start_s0_thread(x, status):
thread = Thread(target=start_s0, args=(x, status))
thread.setDaemon(True)
thread.start()
class Status(object):
def __init__(self, status=True):
self.status = status
self.lock = Lock()
def get_status(self):
with self.lock:
result = self.status
return result
def set_status_OFF(self):
with self.lock:
self.status = False
def initiation_process(counters_status):
status = Status()
config_status = read_config_status()
for x in range(len(counters_status)):
if config_status[x] == "active" and counters_status[x] == False:
print "Nr " + str(x + 1) + " wird gestartet"
counters_status[x] = True
start_s0_thread(x, status)
elif config_status[x] == "inactive" and counters_status[x] == True:
print "Nr " + str(x + 1) + " wird gestoppt"
counters_status[x] = False
status.set_status_OFF()
return counters_status
def main():
counters_status = list()
for x in range(len(read_config_status())):
counters_status.append(False)
while True:
counters_status = initiation_process(counters_status)
sleep(10)
if __name__ == '__main__':
main()
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 13:32
von BlackJack
@mobby: Wenn Du für jeden Zähler einen Status haben möchtest, dann musst Du halt genau das machen: Für jeden Zähler einen Status erstellen und nicht einen für alle. Damit wird die `counter_status`-Liste in der Form unnötig, weil das ja genau das selbe `True` oder `False` drin stehen würde wie in den `Status`-Exemplaren.
Zu dem hatte ich ja schon mal gesagt, dass die Klasse so wie sie jetzt ist, unnötig und überkompliziert ist. Stattdessen sollten man, und auch hier wiederhole ich mich, eher eine Klasse verwenden über die man den Zähler starten, stoppen, und den Status abfragen kann.
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 14:12
von mobby
@BlackJack: Jetzt funktionierts !!!
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import config_datei
from time import sleep
from threading import Thread
def read_config_status():
reload(config_datei)
return config_datei.counterStates
def start_s0(x, status):
print "S0_Zaehler_0" + str(x + 1)
while True:
if status.get_status(x) == False:
print "Thread wird beendet"
break
sleep(5)
def start_s0_thread(x, status):
thread = Thread(target=start_s0, args=(x, status))
thread.setDaemon(True)
thread.start()
class Status(object):
def __init__(self, status=list()):
self.status = status
def add_counters(self):
self.status.append(False)
def get_status(self, x):
return self.status[x]
def set_status_ON(self, x):
self.status[x] = True
def set_status_OFF(self, x):
self.status[x] = False
def initiation_process(status):
config_status = read_config_status()
for x in range(len(config_status)):
if config_status[x] == "active" and status.get_status(x) == False:
print "Nr " + str(x + 1) + " wird gestartet"
status.set_status_ON(x)
start_s0_thread(x, status)
elif config_status[x] == "inactive" and status.get_status(x) == True:
print "Nr " + str(x + 1) + " wird gestoppt"
status.set_status_OFF(x)
def main():
status = Status()
for x in range(len(read_config_status())):
status.add_counters()
while True:
initiation_process(status)
sleep(10)
if __name__ == '__main__':
main()
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 14:22
von pillmuncher
mobby hat geschrieben:Jetzt funktionierts !!!
Nicht so ganz:
Code: Alles auswählen
>>> class Status(object):
... def __init__(self, status=list()):
... self.status = status
... def add_counters(self):
... self.status.append(False)
... def get_status(self, x):
... return self.status[x]
... def set_status_ON(self, x):
... self.status[x] = True
... def set_status_OFF(self, x):
... self.status[x] = False
...
>>> s1 = Status()
>>> s2 = Status()
>>> s1.add_counters()
>>> s1.set_status_ON(0) # <-- s1!!
>>> s2.get_status(0) # <-- s2!!
True
Überraschung!
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 14:35
von mobby
@pillmuncher: Was willst du mir damit sagen? Dass wenn ich zwei Objekte erstelle, aber nur Objekt 1 bearbeite der Wert trotzdem in Objekt 2 geändert wird? Auf jeden Fall nichts, was wünschenswert ist, aber ehrlich gesagt is das in meinem Beispiel eigentlich egal, da eh nur ein Objekt erstellt wird. Aber unabhängig davon, wie vermeide ich das und woher kommt dieser Effekt?
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 15:32
von pillmuncher
@mobby: Der Überltäter ist diese Zeile hier:
Default-Parameter werden nur ein einziges mal erzeugt, nämlich wenn die Funktion, zu der sie gehören, angelegt wird. Danach gelten sie für jeden Aufruf der Funktion. Wenn man da ein veränderbares Objekt (zB. eine Liste) erzeugt, gelten alle Änderungen für
dieses eine Objekt. Das in Python übliche Idiom, mit dem man das umgehen kann, ist dies hier:
Code: Alles auswählen
def __init__(self, status=None):
if status is None:
self.status = []
else:
self.status = status
In deinem Fall ist aber die ganze Weise, wie das Status-Objekt angelegt wird, ungut. Nach dem Erzeugen sollte ein Objekt normalerweise sofort verwendbar sein. Bei dir muss man so oft
add_counters() aufrufen, wie man Felder in einer Liste benötigt. Warum gibst du nicht die Länge der gewünschten Liste als Argument beim Erzeugen deines Status-Objektes an?
Code: Alles auswählen
def __init__(self, length):
self.status = [False] * length
und dann:
Code: Alles auswählen
def main():
status = Status(len(read_config_status()))
dann brauchst du auch kein
add_counters() mehr.
Re: Steuerungs-Skript
Verfasst: Montag 21. Juli 2014, 16:34
von mobby
@pillmuncher: Super, vielen Dank für die ausführliche Erklärung. Den Vorschlag habe ich so eingebaut

Tip Top
Re: Steuerungs-Skript
Verfasst: Sonntag 3. August 2014, 13:53
von mobby
Hey at all,
Update: Habe mein Steuerungsskript inzwischen so weit verbessert, dass sich alle Threads von alleine beenden, sobald dies im Steuerungsskript angewiesen wird. Dies wird über das in diesem Thema erarbeitete Objekt gelöst. Das funktioniert, weil ich in den Threads Aufgaben verteile die über eine While Schleife immer alle x Sekunden abgerufen werden. Bevor die Aufgabe ausgeführt wird, wird der status überprüft und falls er False sein sollte, mittels break die Schleife verlassen. So schließt sich auch automatisch der Thread. Nur jetzt habe ich ein Problem, sollte ich meinen Zähler entfernen und der Status springt auf False, wird mein einer Sub-Thread sofort beendet, da der sleep Timer im Millisekunden Bereich liegt, nur die Aufgabe in meinem Sub-Thread zum Schreiben in die Datenbank wird nur alle 5 / 10 / 15 Minuten abgerufen. Das bedeutet, dass der Sub-Thread und somit der komplette Thread für den Zähler nur bei Eintritt dieses Intervalls beendet wird. Will ich also Zähler 1 neu anlegen, muss ich warten bis das Intervall einmal abgelaufen ist, sonst ist der Thread noch aktiv und macht weiter, weil er wieder den Status auf True erhält.
Ich weiß ist alles etwas kompliziert erklärt, aber im Grunde geht es darum: Wie kann ich meinen Thread beenden, obwohl die Hauptaufgabe nur alle 5 Minuten ausgeführt wird? Hier mal meine bisherige Vorgehensweise. Dabei handelt es sich um einen Sub-Thread der sich selbst beenden soll, sobald status.get_status(x) auf False springt:
Code: Alles auswählen
def write_value(status, x, count, intervall, table_name):
timestamp = int(time.time() / intervall) * intervall
while True:
timestamp += intervall
time.sleep(max(0, timestamp-time.time()))
s0_value = count.get_and_reset()
datum = str(time.strftime("%d-%m-%Y"))
uhrzeit = str(time.strftime("%H:%M:%S"))
if status.get_status(x) == False:
break
else:
db.insert_into_database(status, x, table_name, timestamp, datum,
uhrzeit, s0_value
)
Vielen Dank für Hile !!!
Gruß
mobby
Re: Steuerungs-Skript
Verfasst: Sonntag 3. August 2014, 14:15
von Sirius3
@mobby: statt selbst was zu erfinden, nimm doch das, was es schon gibt und was dafür gemacht wurde. In Deinem Fall 'threading.Event':
Code: Alles auswählen
def write_value(event, x, count, intervall, table_name):
timestamp = int(time.time() / intervall) * intervall
while not event.wait(max(0, timestamp-time.time())):
timestamp += intervall
s0_value = count.get_and_reset()
datum = str(time.strftime("%d-%m-%Y"))
uhrzeit = str(time.strftime("%H:%M:%S"))
db.insert_into_database(True, x, table_name, timestamp, datum, uhrzeit, s0_value)
und irgendwoanders:
Re: Steuerungs-Skript
Verfasst: Sonntag 3. August 2014, 16:35
von mobby
@Sirius3: Perfekt, nach genau sowas habe ich gesucht. Vielen Dank für den Hinweis, jetzt läuft alles tadellos!
