Seite 1 von 1

globale Variablen lesen und setzen

Verfasst: Donnerstag 30. Oktober 2014, 08:38
von sb_newsletter
Liebe Forum Mitglieder,

gestern bin ich auf die tolle Idee gekommen eine Steuerung mit dem Raspberry schreiben zu wollen, Doch bevor man damit beginnen kann müsste ich mich in Python ersteinmal einarbeiten.... und komme bei der Problematik "globaler Variablen" leider nicht weiter und würde mich sehr freuen wenn ihr mir bei diesem Unterfangen behilflich sein könntet

Source:

Code: Alles auswählen

from time import sleep
import threading
from multiprocessing import Process
import os, sys

G = None;

def Proz_SetupDevices():
	i = 1;
	while i <= 20:
		i = i + 1
		print "Variable", i, G
		sleep(0.5)
def Proz_ReadInput():
	global G
	print "Foo2Start"
	G = 100;
	return G
	
if __name__ == '__main__':
	BW_SetupDevices = Process(target=Proz_SetupDevices)
	BW_ReadInput = Process(target=Proz_ReadInput)
		
	BW_SetupDevices.start()
	sleep(1)
	BW_ReadInput.start()
	BW_ReadInput.join()
	print G;
Ausgabe:

Code: Alles auswählen

root@raspberrypi:/home/pi# python Sample.py
Variable 2 None
Variable 3 None
Variable 4 None
Foo2Start
None
Variable 5 None
Variable 6 None
Variable 7 None
Variable 8 None
Variable 9 None
Variable 10 None
Variable 11 None
Variable 12 None
Variable 13 None
Variable 14 None
Variable 15 None
Variable 16 None
Variable 17 None
Variable 18 None
Variable 19 None
Variable 20 None
Variable 21 None
root@raspberrypi:/home/pi#
Problem:

nachdem der Backroundworker "BW_ReadInput" gestartet wurde müsste doch der noch aktive BW "BW_SetupDevices" die aktuelle "G" Variable mit dem neuen Wert "100" ausspucken....
habt vielen lieben dank für eure Bemühungen, ich hoffe ihr könnt mir den Start vereinfachen....

Re: globale Variablen lesen und setzen

Verfasst: Donnerstag 30. Oktober 2014, 09:08
von Sirius3
@sb_newsletter: neben der allgemeinen Bemerkung, dass es keine globale-Variablen-Problematik gibt, weil die Lösung einer solchen Problematik immer die ist, dass man globale Variablen nicht mehr benutzt, hier der spezielle Fall, warum man keine globalen Variablen benutzen sollte:
multiprocessing startet zwei Prozesse in unterschiedlichen Addressräumen. Damit ist es dem einen Prozess egal, ob der andere irgendwelche Variablen ändert. multiprocessing bietet spezielle Methoden, um Daten zwischen den Prozessen auszutauschen, Queues, Events, etc.

Re: globale Variablen lesen und setzen

Verfasst: Donnerstag 30. Oktober 2014, 09:22
von sb_newsletter
könntest du mir bitte hierzu ein Beispiel anhand des obigen quellcodes geben, wie gesagt habe gestern meine ersten gehversuche unternommen :-)

hab vielen lieben dank für deine Bemühungen

stefan

Re: globale Variablen lesen und setzen

Verfasst: Donnerstag 30. Oktober 2014, 10:26
von BlackJack
@sb_newsletter: Ich würde ja als erstes mal fragen ob es überhaupt mehrere *Prozesse* sein müssen. Und falls ja, und wenn dafür `multiprocessing` verwendet werden soll, ob das dann wirklich *so* organisiert werden muss, also dass man so frei alles selber basteln muss, statt zum Beispiel asynchron Funktionen in anderen Prozessen laufen zu lassen und denen Werte zu übergeben und Rückgabewerte zu bekommen, und damit die ganze Interprozesskommunikation halbwegs transparent erledigen zu lassen.

Anmerkungen zum Quelltext: Es gibt einen Style Guide for Python Code, da lohnt sich ein Blick bezüglich der Namensschreibweise und vor allem auch der Einrücktiefe. Das sind konventionell nämlich vier Leerzeichen pro Ebene.

Typ-Pre- oder Postfixe die kein „duck type” sind sollte man nicht in Namen schreiben. Und Abkürzungen die nicht allgemein bekannt sind, sollte man vermeiden. Funktionen sollten zum Beispiel kein `Proz_` im Namen haben. Funktionen und Methoden werden üblicherweise nach Tätigkeiten benannt und damit kann man sie dann auch von anderen Werten hinreichend unterscheiden.

Es gibt drei unbenutzte Importe.

Die ``while``-Schleife in `setup_devices()` würde man eher als ``for``-Schleife schreiben.

Semikolons am Zeilenende sind in Python nicht nötig.

Das ``return`` in `read_input()` macht keinen Sinn weil dieser Wert nirgends benutzt oder gar erwartet wird.

Auch das Hauptprogramm sollte in einer Funktion stehen, üblicherweise `main()` genannt, damit man dort nicht modulglobale Werte einführt.

Wenn man einen Thread oder Process startet um sofort danach `join()` darauf aufzurufen, braucht man an der Stelle ganz offensichtlich keine Nebenläufigkeit und hätte ganz einfach die Funktion normal aufrufen können. Dann würde auch das ``return`` in der Funktion Sinn machen.

Das ganze mal mit Threads und einer Queue:

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import absolute_import, division, print_function
from time import sleep
from Queue import Empty, Queue
from threading import Thread


def setup_devices(queue):
    value = None
    for i in xrange(2, 21):
        print('Variable', i, value)
        try:
            value = queue.get(timeout=0.5)
        except Empty:
            pass  # Intentionally ignored.


def read_input(queue):
    print('Foo2Start')
    value = 100
    queue.put(value)
    return value


def main():
    queue = Queue()
    device_setup = Thread(target=setup_devices, args=(queue,))
    device_setup.start()
    sleep(1)
    value = read_input(queue)
    print(value)


if __name__ == '__main__':
    main()

Re: globale Variablen lesen und setzen

Verfasst: Donnerstag 30. Oktober 2014, 11:12
von MagBen
So geht's:

Code: Alles auswählen

from time import sleep
from multiprocessing import Process, Value
 
G = Value("i",0)
 
def Proz_SetupDevices():
        i = 1;
        while i <= 20:
                i = i + 1
                print "Variable", i, G.value
                sleep(0.5)
                
def Proz_ReadInput():
        global G
        print "Foo2Start"
        G.value = 100
        return G
       
if __name__ == '__main__':
        BW_SetupDevices = Process(target=Proz_SetupDevices)
        BW_ReadInput = Process(target=Proz_ReadInput)
               
        BW_SetupDevices.start()
        sleep(1)
        BW_ReadInput.start()
        BW_ReadInput.join()
        print G.value
Die Semikolons brauchst Du in Python übrigens (fast) nicht.

Hier kannst Du sehen was es für weitere Möglichkeiten gibt Daten zwischen Prozessen auszutauschen
https://docs.python.org/2/library/multi ... -processes

Re: globale Variablen lesen und setzen

Verfasst: Donnerstag 30. Oktober 2014, 11:28
von Sirius3
@MagBen: so geht's nicht. Das schafft einen völlig undurchsichtigen Zustand zweier Prozesse, der unweigerlich bei komplexeren Problemen zu nicht findbaren Fehlern führt. Globale Variablen sind an sich schon schwierig zu handeln. Wenn dazu noch mehrere parallel laufende Funktionen hinzukommen, ist überhaupt nicht mehr vorhersehbar, wann sich ein globaler Zustand ändert.
global in Zeile 14 ist überflüssig.

Re: globale Variablen lesen und setzen

Verfasst: Donnerstag 30. Oktober 2014, 11:34
von snafu
@MagBen: Auf die globale Variable würde ich verzichten und besser ein ``Value``-Objekt als Argument an die entsprechenden Funktionen übergeben. Übrigens können hierbei Werte verschluckt werden, wenn der produzierende Prozess schneller neue Werte schreibt als der konsumierende Prozess verarbeiten kann. Hier empfiehlt sich stattdessen die Verwendung einer ``Queue``.

Will man diese Tipps beachten, dann läuft es im Grunde auf genau das hinaus, was BlackJack bereits mit seinem Codebeispiel gezeigt hat.