while-Schleife durch eine Funktion beenden

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
stsemant
User
Beiträge: 31
Registriert: Sonntag 24. Dezember 2017, 13:06

Sehr geehrtes Forum,

ich komme mal wieder mit einem Problem um die Ecke. Ich hoffe, dass die Überschrift nicht allzu dämlich gewählt ist.

Hier erstmal der code:

Code: Alles auswählen

import time
from threading import Timer


def f_event_01():
	print "event wird ausgefuehrt", time.time()
	Timer(10, f_event_01, ()).start()
	

if __name__ == "__main__":
	
	Timer(10, f_event_01, ()).start()
	
	print "ende"
	
	while True:				# 1
		
		flag = True	
		
		while flag == True:		# 2
			
			print "Messwerte aufnehmen"
			
			print "Messwerte in ein Tupel schreiben"
			
			print "Tupel an eine Datenbank senden"
			
		print "irgendetwas nach while-Schleife #2"
Ich habe eine Endlosschleife (#1) und in ihr drin noch eine weitere (#2). #2 führt die ganze Zeit Anweisungen aus, wie sie in den print-Anweisungen stehen. Nun hab ich weiterhin einen Timer am laufen. Alle 10 Sekunden soll er das tun, was in seiner entsprechenden Funktion steht (f_event_01). DAs tut er auch. Weiterhin soll aber auch Schleife #2 direkt beenden. Es wäre auch nicht weiter schlimm, wenn die #2 bis zum Ende durchläuft, dann soll aber Schluss sein :) Ein return flag in f_event_01 bringt mir nichts, glaube ich, da ich in #2 die Funktion ja nicht explizit aufrufe.

Hoffentlich kann mir jemand helfen. Ich hoffe, dass ich mich deutlich ausgedrückt habe.

by the way: gibt es noch andere ( vielleicht sogar bessere ) Möglichkeiten in python timer, schedules oder watchdogs zu realisieren? Ich event, dass immer zu einem vorher festgelegten Zeitpunkt ausgeführt wird, wäre optimal. Denn bei dieser timer-Lösung habe ich im eine knappe Milisekunde Verzögerung, was natürlich nicht kriegsentscheidend ist, aber schöner wäre es ohne...
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

mir ist gerade nicht klar, wann die while-Scheife #2 nicht mehr ausgeführt werden soll? Wenn der Timer-Thread das 1. mal gelaufen ist? Oder wann?
by the way: gibt es noch andere ( vielleicht sogar bessere ) Möglichkeiten in python timer, schedules oder watchdogs zu realisieren?
Was hast du denn genau vor? Der Code, den du gepostet hat, lässt ja schlecht bis gar nicht auf dein wahres Vorhabens schließen.

Und welches Betriebssystem benutzt du?

Gruß, noisefloor
stsemant
User
Beiträge: 31
Registriert: Sonntag 24. Dezember 2017, 13:06

Die Schleife soll immer beendet werden, sobald der timer ausgeführt wurde.

Das ganze Programm soll am Ende Messwerte aufnehmen, verarbeiten und in eine Datenbank schreiben. In einem definierten Zyklus, welcher durch den timer eingehalten werden soll, sollen die Werte aus der Datenbank entnommen werden, dann min, max und Mittelwert bilden und diesen Wert in eine andere Datenbank schreinen. In #2 sollen regelmäß0ig noch andere Dinge geschehen, Textdateien auslesen, , emails versenden usw.

Das ganze soll später auf einem PI mit raspbian jessie laufen.
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

da sehe ich gerade keinen Grund, warum man das alles in ein Skript packen sollte. Das sind verschiedene Dinge, die dürfen von verschiedenen Skripten erledigt werden.

Raspbian Jessie (warum nicht das neuere Stretch?) hat systemd an Bord, heißt:
* periodische Aufgaben kannst du über systemd Timer Units machen (alternativ: cron)
* wenn du das Skripte / die Skripte über eine systemd Service Unit startest, kannst du es über die passenden Direktiven auch neu starten lassen, wenn es mal crashen sollte.

Wenn du es unbedingt "all in one" machen willst: starte für jeden Aufgabe einen Thread oder einen Prozess und lasse diese über Queue und / oder Events mit einander kommunizieren. Das "Hauptprogramm" sollte nur die Threads / Prozesse starten und sonst nichts machen.
Aber, wie gesagt, robuster und einfacher sind unabhängige Skripte.

Gruß, noisefloor
stsemant
User
Beiträge: 31
Registriert: Sonntag 24. Dezember 2017, 13:06

über systemd und cron habe ich natürlich auch schon nachgedacht. Das Problem ist aber, dass diese zeitlich gesehen nicht genau genau arbeiten (ohne die prioritäten hierfür zu ändern). Diese beispielsweise 10 Sekunden-Intervalle sollen auf die milisekunde genau aufgerufen werden (+- 1 ms). Deswegen wollte ich alles python-intern laufen lassen. Aber ja , der Einwand alles in threads und prozesse zu packen ist natürlich das Naheliegendste. Werde ich wahrscheinlich auch so machen. Kannst du mir bezüglich threads, prozesse, queue und events weitere Schlageworte geben, ob es zum Beispiel spezielle librarys dafür gibt. Auf dem Gebiet habe ich mich noch garnicht bewegt.
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Diese beispielsweise 10 Sekunden-Intervalle sollen auf die milisekunde genau aufgerufen werden (+- 1 ms). Deswegen wollte ich alles python-intern laufen lassen
Was verleitet dich denn zur der Annahme, dass Python das kann bzw. macht? Tut's nämlich nicht. Bzw. das ist nicht Python-spezifisch, das trifft auf alle Prozesse im Userspace zu. Dein Skript bekommt vom Linux-Kernel Rechenzeit zugeteilt - wann entscheidet der Scheduler des Kernels alleine. Und beim Standardkernel kriegst du das mit Sicherheit nicht so genau hin. Da brauchst du auf jeden Fall einen Echtzeitkernel.

Und dann ist auch der (vergleichsweise lahme) Raspi nicht die richtige Wahl an Hardware. Und warum brauchst du eine Genauigkeit von 1 Millisekunde?
ob es zum Beispiel spezielle librarys dafür gibt.
Ist alles bei Python an Bord: die Module heißen für Python 3 threading, mulitprocessing und concurrent.futures.

Gruß, noisefloor
stsemant
User
Beiträge: 31
Registriert: Sonntag 24. Dezember 2017, 13:06

Danke für den Hinweis. Ich weiß ja, dass es vom kernel abhängt. Ich hab mich vielleicht auch etwas flasch ausgedrückt,

Mir ist auch garnicht so wichtig, dass der Abstand von 10 Sekunden auf die Millisekunde eingehalten wird, sondern vielmehr, dass dieses event (oder thread oder was auch immer) immer pünktlich ausgeführt wird, also: beispielsweise: 16:05:00,000 , 16:05:10,000 , 16:05:20,000 , 16:05:30,000 usw.. Und auch hier wäre es nicht schlimm, wenn sich ein event mal um ein paar Millisekunden verspätet, solange das nur keine Auswirkungen auf den nächsten "Termin" hat. Wenn ich nämlich dieses Messgerät über ein paar Monate laufen lasse, und ich habe jedesmal nicht 10 Sekunden-Abstände, sondern 10,01s, dann hab ich nach ein paar Monaten nicht beispielsweise 10.000 Mittelwerte, sondern 10.050. Und das sieht dann erstmal komisch aus. Deswegen war ja auch meine Frage unter anderem, ob es nicht (abgesehen von systemd) eineb timer gibt, dem ich sage, dass er bei Sekunde 1516482069.00 nach unix' Geburt auslösen soll.

Aber insgesamt hast du mir schon sehrr geholfen, vielen Dank!!!
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@stsemant: man kann eine Schleife programmieren, die sich mit der Systemzeit synchronisiert.
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

soweit ich das verstehen, willst du doch "nur" alle 10 Sekunden den Mittelwert usw berechnen? Dann macht man das _nicht_ exakt alle 10 Sekunden, sondern du schreibst für jeden Datensatz einen Timestamp in die DB, dann kannst du darüber später (=irgendwann) gruppieren und rechnen.

Es exakt alle 10 Sekunden machen zu wollen würde ich als überflüssig aka broken-by-design bezeichnen.

Abgesehen davon: du kannst auch den Timer von systemd auf eine Genauigkeit von 1 Mikrosekunden einstellen, siehe: https://www.freedesktop.org/software/sy ... curacySec=
Ob das dann aber auch wirklich exakt läuft... siehe oben.

Basierend auf deiner Beschreibung würde ich auch mal sagen, dass du mir einem Mikrocontroller zur Messwerterfassung besser bedient bist. Da kannst du auch sicher sein, dass der ohne Murren monatelang durchläuft. Wenn du bei Python bleiben willst: es gibt MicroPython, eine Implementierung von Python für Microcontoller wie z.B. den ESP32, ESP8266 und andere.

Gruß, noisefloor
Antworten