Globale Namen definieren ???
@lackschuh: Das ist immer noch alles sehr missverständlich formuliert. Was heisst zu Beginn des Programms? Im Quelltext auf Modulebene? Nein, da definiert man keine Variablen. Die Variable taucht auch nicht in mehreren Funktionen einfach so auf. Werte, ausser Konstanten, betreten Funktionen als Argumente. Welchen Wert der Name lokal dabei bekommt ist unabhängig davon an welchen Namen er bei einem Aufrufer gebunden ist.
@lackschuh: Wenn die Variable nicht verändert wird oder wenn die Variable als gemeinsamer Startwert gilt, dann kann man sie situationsabhängig als Konstante definieren. Im Falle eines Startwertes sollte man den Startwert an einen neuen Namen binden und Veränderungen dann mit diesem neuen Namen durchführen. Zwar ist der neue Name zunächst nur eine Referenz auf das selbe Zahl-Objekt, welches auch von der Konstante referenziert wird, aber nach einer Rechenoperation wird ja ohnehin ein neues Zahl-Objekt als Resultat erzeugt und dieses wird dann halt neu an den zusätzlichen Namen gebunden (ich hoffe du kannst mir bis hier noch folgen). Somit kommt man gar nicht auf die Idee, irgendwas mit `global` hinzupfuschen. Wie gesagt: Das alles immer unter der Annahme, dass sich andere Funktionen ebenfalls nur für den Startwert und nicht für den veränderten Wert interessieren. Falls letzteres zutrifft, dann handelt es sich definitiv um keine Konstante, sondern um eine tatsächlich veränderliche Variable, dessen Definition man auf Modulebene vermeiden sollte.
Hallo
Danke für die Infos.
Also zB habe ich Startwerte oder Flags, welche zu Beginn im Quelltext den Wert '''0''' haben. Wie könnte man es anhand des unteren Beispiels erklären, wie global zu vermeiden wäre?. Die Erklärung von snafu verwirrt mich leicht bzw. ich kapier sie wohl nicht ganz :K
Vielen Dank
Danke für die Infos.
Also zB habe ich Startwerte oder Flags, welche zu Beginn im Quelltext den Wert '''0''' haben. Wie könnte man es anhand des unteren Beispiels erklären, wie global zu vermeiden wäre?. Die Erklärung von snafu verwirrt mich leicht bzw. ich kapier sie wohl nicht ganz :K
Code: Alles auswählen
status = 0
class EmailThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global status
while True:
#mach was
if habe_mail == 1: # status wird auf 1 gesetzt
status = 1
def main():
global status
while True:
if status == 0:
pass # mach nichts
elif status = 1:
# Aufruf weiterer Funktionen
Durch eine Queue-Objekt, welches du aus der main-Funktion dem E-Mail-Thread übergibst. Dann sparst du dir auch das Busy-Waiting und treibst deine Stromrechnung nicht in ungeahnte Höhen.
Das Leben ist wie ein Tennisball.
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Aber man bekäme doch einen Teil davon wieder herein durch die ansonsten anfallenden Heizkosten, die man sich dadurch spart. Ich meine, angesichts des Wetters heute...EyDu hat geschrieben:...sparst du dir auch das Busy-Waiting und treibst deine Stromrechnung nicht in ungeahnte Höhen.
In specifications, Murphy's Law supersedes Ohm's.
@lackschuh: Wie man das Beispiel am besten löst, hängt davon ab wie und was die beiden Threads eigentlich miteinander kommunizieren sollen. Ich sehe da denn Sinn von dem Flag nicht, beziehungsweise nicht wie man das mit vertretbarem Aufwand threadsicher hinbekommt ohne das der Thread der die Emails dann verarbeitet, den Test ob neue E-Mails vorhanden sind, nicht zumindest implizit noch man selber machen muss.
@lackschuh: je nach Anwendungsfall bekommst Du bei Deinem Ansatz Probleme, wenn mehr als eine Mail kommt. Wie läuft die Verarbeitung der Mails, wie wird der Inhalt von einem Thread zum anderen übertragen? Queues sind eine Möglichkeit, das sauber abzubilden.
@lackschuh:
Die Sinnhaftigkeit Deines Beispiels mal ausser Acht lassend hier das Beispiel ohne globale Variable und in threadsafe:
Die Sinnhaftigkeit Deines Beispiels mal ausser Acht lassend hier das Beispiel ohne globale Variable und in threadsafe:
Code: Alles auswählen
# Weg damit, globals sind vorallem mit Threads Ausgeburten der Hölle!
# status = 0
class EmailThread(threading.Thread):
def __init__(self, status):
threading.Thread.__init__(self)
self.status = status
def run(self):
#global status
while True:
#mach was
if habe_mail == 1: # status wird auf 1 gesetzt
self.status.set()
def main():
#global status
# anstelle der globalen Variable nehmen wir eine threadsichere boolsche Variable.
status = threading.Event()
while True:
if not status.is_set():
pass # mach nichts
# vllt. dem Teil ein sleep gönnen ;)
#elif status = 1:
# nix elif hier, da eh nur 1|0 unterschieden wird
else:
...
# Aufruf weiterer Funktionen
...
# iwie fehlt noch der Aufruf des Mailthreads (am besten vor dem while, sonst wird das nie erreicht),
# da kommt das Flag mit rein:
emailthread = EmailThread(status)
# und hier rennt er los ...
emailthread.start()
@jerch: Ob das wirklich threadsafe (genug) ist kommt aber ganz darauf an was dieses Flag bedeutet und wer das wieder löscht.
@jerch: Wie gesagt das kommt darauf an was das bedeutet und wer es wieder löscht und was zwischen Abgfragen und Setzen/Löschen auf den beiden Seiten passiert. Das Flag selber schützt ja nichts oder synchronisiert irgendwie vor gleichzeitigem verändern von gemeinsam benutzten Ressourcen. Zum Beispiel E-Mails auf einem Server, falls der Hauptthread das Flag als Anlass nimmt neue Mails zu verarbeiten. Wirklich sicher erscheint mir das nur wenn der Hauptthread das tatsächlich nur als Flag sieht das er nur liest, und bei dem es nichts ausmacht wenn er nicht alle Änderungen tatsächlich mitbekommt.
Hallo
Hier noch ein aktuelles Beispiel, wo ich nicht weiss, wie ich es anders lösen soll.
Der Startwert ist 150 und von diesem Wert wird nach jedem Buttonkick 1 abgezogen. Mit jedem Klick wird aber die Funktion neu aufgerufen. Wie kann ich hier auf global verzichten?
mfg
Hier noch ein aktuelles Beispiel, wo ich nicht weiss, wie ich es anders lösen soll.
Code: Alles auswählen
x = 150
@route('/home', method='GET')
def index():
global x
p = pipan.PiPan()
if request.GET.get("right"):
right = int(request.GET.get("right"))
x = x - right
print x
p.do_pan(x)
mfg
@lackschuh: Ich würde mal behaupten der Code ist fehlerhaft weil er davon ausgeht, dass jede Webanfrage vom selben Prozess beantwortet wird, was man so allgemein nicht garantieren kann.
Man würde hier den Wert immer mit durch die Anfrage schleifen, oder in ein Cookie packen, oder ein Session-Cookie verwenden und den Wert in einer Datebank speichern wo man ihn mit Hilfe des Session-Cookie dem Client zuordnen kann.
Es sei denn der Wert ist tatsächlich global für alle Anfragen gültig, egal von welchem Client, dann kann der einfach so in die Datenbank.
Man würde hier den Wert immer mit durch die Anfrage schleifen, oder in ein Cookie packen, oder ein Session-Cookie verwenden und den Wert in einer Datebank speichern wo man ihn mit Hilfe des Session-Cookie dem Client zuordnen kann.
Es sei denn der Wert ist tatsächlich global für alle Anfragen gültig, egal von welchem Client, dann kann der einfach so in die Datenbank.
@lackschuh: Würde ich nicht sagen. Bevor man selber etwas schreibt was die Daten persistent und sicher/konsistent bei nebenläufigem Zugriff speichert, kann man auch gleich eine Datenbank verwenden. Weniger potential etwas falsch zu machen und letztendlich wohl auch einfacher zu benutzen als sich so etwas selber zu schreiben. Man muss ja keine Oracle Enterprise Datenbank aufsetzen, SQLite3 tut's ja auch.
Andererseits könnte es Sinn machen die Servosteuerung in einen eigenen Server zu stecken um damit zu erzwingen dass das Gerät immer nur von einem Prozess aus angesteuert wird. Dann könnte sich dieser Prozess auch den aktuellen Zustand merken und ihn abfragbar machen.
Andererseits könnte es Sinn machen die Servosteuerung in einen eigenen Server zu stecken um damit zu erzwingen dass das Gerät immer nur von einem Prozess aus angesteuert wird. Dann könnte sich dieser Prozess auch den aktuellen Zustand merken und ihn abfragbar machen.