Seite 1 von 1
Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 12:52
von Scholastik
Hallo zusammen,
wie können zwei Skripte miteinander kommunizieren?
Also jedes Skript hat eine Klasse, die nach Start in Dauerschleife ihre eigenen Aufgaben ausführt. So gesehen könnte man sie getrennt laufen lassen.
Aber die beiden Skripte sollen Einfluss aufeinander nehmen können. Zb. den Wert einer self Variablen des anderen Skripts abfragen oder evlt sogar ändern können.
Einfachste Lösung wäre sicherlich alles in dasselbe Skript zu verschieben, dann sollten die Klassen ja aufeinander zugreifen können, oder?
Aber wenn ich der Übersicht halber nun 2 Skripte möchte, wie geht das dann?
Wenn ich in Skript A das Skript B importiere, dann funktioniert der Zugriff nur in eine Richtung, nicht in beide, oder?
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 13:32
von pixewakb
Beide Module (?) in ein Skript importieren und dort z. B. in Dauerschleife laufen lassen.
Nur mal laut gedacht - obige Lösung ist m. E. die allein glücklich machende:
Wenn beide Skripte auf das identische Datenmaterial zugreifen, dann kann man halt einem Skript sagen, dass es auf ein Ereignis warten soll oder regelmäßig prüfen soll, ob neue Daten hinzugekommen sind.
PS: Ein Skript mit einer Klasse klingt nach Java und nicht nach Modulen in Python.
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 13:38
von Sirius3
@Scholastik: Übersichtlichkeit kann man durch strukturierte Programmierung erreichen, z.B. in dem man verschiedene Aufgaben in unterschiedliche Module packt. Wenn aber beide Klassen voneinander abhängen, hast Du de facto keine getrennten Module. Um aber eine qualifizierte Antwort geben zu können, brauchen wir mehr Informationen, was Du konkret versuchst zu erreichen.
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 14:38
von Scholastik
Danke.
Ich stelle mir das ganze so vor, dass beides parallel läuft, also zb das eine ist eine websocket verbindung:
Code: Alles auswählen
import pusherclient #live stream client: https://github.com/ekulyk/PythonPusherClient
import time
class pusher_ws:
def __init__(self):
self.datas = []
def runner(self):
self.pusher = pusherclient.Pusher("abcdef")
self.pusher.connection.bind('pusher:connection_established', self.connect_handler)
self.pusher.connect()
def connect_handler(self,data):
xy_channel = self.pusher.subscribe("xy")
xy_channel.bind('xy', self.xy_callback)
def xy_callback(self,data):
self.datas.append(data) # make something with data
if Haupt.counter > 10:
self.datas = []
Haupt.counter = 0
class Hauptskript:
def __init__(self):
self.counter = 0
def starten(self):
WS.runner()
while True:
self.counter += 1
time.sleep(1) # do something
if self.counter > 10:
WS.datas = [] # delete datas from ws
self.counter = 0
if __name__ == '__main__':
WS = pusher_ws()
Haupt = Hauptskript()
Haupt.starten()
Es werden beide Klassen imselben Skript (Skript==eine .py Datei) gestartet. Deswegen denke ich, dass nun beide Klassen durch Verwendung der Globalen Variable aufeinander zugreifen können.
Wenn ich nun aber die "class pusher_ws" in einem eigenen Skript hätte und importiere, wird die Abfrage nach "Haupt.counter" im pusher skript einen Fehler produzieren.
Wie erreiche ich also dasselbe Ergebnis, als wenn ich beide mithilfe der globalen Variable imselben Skript verbinde?
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 15:04
von __deets__
Das erreichst du, indem du in deinem Fall die geteilte Datenstruktur an beide Instanzen uebergibst, statt ueber globale Variablen zu arbeiten.
Code: Alles auswählen
class Pusher(object):
def __init__(self, queue):
self._queue = queue
class WasAnderes(object):
def __init__(self, queue):
self._queue = queue
def main():
q = Queue.Queue()
pusher = Pusher(q)
was_anderes = WasAnderes(q)
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 15:41
von Scholastik
__deets__ hat geschrieben:Das erreichst du, indem du in deinem Fall die geteilte Datenstruktur an beide Instanzen uebergibst, statt ueber globale Variablen zu arbeiten.
Danke
Ich habe deinen Lösungsvorschlag nun so verstanden, dass ich immer, wenn ich interagieren will, mit put() etwas an queue übergebe, und mit get() dies dann im anderen skript abrufen kann?
Und zwar würde ich es so machen:
- Wenn counter>10 würde ich queue.put("reset") machen und counter 0 setzen.
- im callback des pushers mache ich queue.get(False) um zu sehen, ob was in der queue ist. wenn nicht dann weiter, wenn doch und es "reset" string ist, dann datas löschen.
Allerdings scheint mir das doch eine ziemlich umständliche Lösung zu sein, die besonders unübersichtlich wird, wenn ich neben dem "reset" befehl noch 100 andere Befehle übergeben wollen würde und weitere pusher callbacks hätte. Dann macht das ganze queue System doch eig keinen Sinn mehr, weil sie ja garnicht zwingend in einer Reihenfolge abgearbeitet werden müssen.
Aber ich glaub der wichtige Ansatz den du mir mitteilen wolltest, ist ein geteiltes/gemeinsames Objekt zu übergeben.
Vielleicht anstelle von queue zb. einfach ein Dictionary übergeben, in dem veränderte Werte dann in beiden Skripten bekannt werden?
Sollte funktionieren, aber ist das auch sinnvoll? Zb. im Bezug darauf, wenn im einem Skript zb. gerade über das dictionary iteriert wird, während es vom anderen skript geändert wird
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 16:32
von BlackJack
@Scholastik: Genau wegen solcher Probleme nimmt man eine Queue. Die ist „threadsicher“ und man hat eine Reihenfolge damit nichts durcheinander geht. Wenn Du da mehr Freiheiten möchtest, musst Du Dich auch selbst um die Probleme kümmern (Sperrmechanismen aus `threading`) und dann sollte das nach Möglichkeit auch mehr Parallelität bieten als die Queue, denn sonst hätte man Arbeit in etwas gesteckt und mehr Fehler riskiert, als wenn man gleich eine Queue verwendet hätte.
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 17:04
von Scholastik
BlackJack hat geschrieben:@Scholastik: Genau wegen solcher Probleme nimmt man eine Queue. Die ist „threadsicher“ und man hat eine Reihenfolge damit nichts durcheinander geht. Wenn Du da mehr Freiheiten möchtest, musst Du Dich auch selbst um die Probleme kümmern (Sperrmechanismen aus `threading`) und dann sollte das nach Möglichkeit auch mehr Parallelität bieten als die Queue, denn sonst hätte man Arbeit in etwas gesteckt und mehr Fehler riskiert, als wenn man gleich eine Queue verwendet hätte.
Das dictionray könnte ungefähr so aussehen:
Befehlsdict = {"counterreset":False,"xyreset":False,"AktuelleDatas":[5,6,7],"AndereInformationen":{"abc":1,"cdf":[2,3,4,5]}}
Anstatt jeden einzelnen eintrag ala queue.put("counterreset") zu übergeben, könnte ich vermutlich auch einfach das komplette Befehlsdict durch queue übergeben, oder? Das war mir vorher nicht ganz klar

Dann könnte es wiederum also doch gut funktionieren.
Werde versuchen es umzusetzen und wenn dabei Probleme auftreten, meld ich mich nochmal
Danke.
PS:
doch noch ne kurze Frage:
Wenn ich ein dictionary über queue übergebe, ist es dann eine deepcopy oder ist es nur ein Verweis? Damits fehlerfrei läuft (wenn das dictionary so wie oben aussieht), sollte man ja eine vollständige Kopie verwenden, deswegen frag ich. Also lieber eine deepcopy des dictionaries an queue übergeben? Ja, oder?
edit:
Das Haupskript übergibt das dictionary nun mit queue.put . Im pusher skript möchte ich aber immer nur das aktuellste dictionary haben. Wie setze ich das um? Also in dem Fall, dass es häufiger im hauptskript aktualsiert wird, als es das pusher skript abruft. Dann würden sich ja zb 11 einträge in queue befinden, von denen ich nur eines brauche. Selbst mit LiFO würde queue dadurch unnötig groß. Also jedesmals wenn bevor ich put() mache, alles in queue löschen?? Das klingt verkehrt.
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 19:13
von EyDu
Scholastik hat geschrieben:Das Haupskript übergibt das dictionary nun mit queue.put . Im pusher skript möchte ich aber immer nur das aktuellste dictionary haben. Wie setze ich das um? Also in dem Fall, dass es häufiger im hauptskript aktualsiert wird, als es das pusher skript abruft. Dann würden sich ja zb 11 einträge in queue befinden, von denen ich nur eines brauche. Selbst mit LiFO würde queue dadurch unnötig groß. Also jedesmals wenn bevor ich put() mache, alles in queue löschen?? Das klingt verkehrt.
Darauf wurde weiter oben schon kurz eingegangen. Um das entscheiden zu können, müsstest du das geplante Verhalten deines Programms etwas genauer festlegen, bzw. darstellen wie die beiden Module miteinander interagieren. Soll das empfangende Modul sich einfach nur den aktuellen Wert schnappen und damit rechnen, oder soll dessen Berechnung erst angestoßen werden, wenn tatsächlich auch ein neuer Wert da ist (und dabei ggf. alle älteren Werte ignoriert)?
Re: Interaktion zwischen zwei Skripten?
Verfasst: Freitag 7. Juli 2017, 19:31
von Scholastik
EyDu hat geschrieben:Scholastik hat geschrieben:Das Haupskript übergibt das dictionary nun mit queue.put . Im pusher skript möchte ich aber immer nur das aktuellste dictionary haben. Wie setze ich das um? Also in dem Fall, dass es häufiger im hauptskript aktualsiert wird, als es das pusher skript abruft. Dann würden sich ja zb 11 einträge in queue befinden, von denen ich nur eines brauche. Selbst mit LiFO würde queue dadurch unnötig groß. Also jedesmals wenn bevor ich put() mache, alles in queue löschen?? Das klingt verkehrt.
Darauf wurde weiter oben schon kurz eingegangen. Um das entscheiden zu können, müsstest du das geplante Verhalten deines Programms etwas genauer festlegen, bzw. darstellen wie die beiden Module miteinander interagieren. Soll das empfangende Modul sich einfach nur den aktuellen Wert schnappen und damit rechnen, oder soll dessen Berechnung erst angestoßen werden, wenn tatsächlich auch ein neuer Wert da ist (und dabei ggf. alle älteren Werte ignoriert)?
Es soll schon so wie im ersten code beispiel laufen.
Also beides läuft unabhängig voneinander, aber beides Zugriff auf ein aktuelles gemeinsames dictionary haben (im ersten code symbolisiert durch self.counter).
Um deine Frage also direkt zu beantworten, soll eine ständig wiederholt aufgerufene Funktion sich den aktuellsten Wert schnappen.