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?
Interaktion zwischen zwei Skripten?
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.
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.
@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.
-
- User
- Beiträge: 53
- Registriert: Freitag 7. Juli 2017, 12:35
Danke.
Ich stelle mir das ganze so vor, dass beides parallel läuft, also zb das eine ist eine websocket verbindung:
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?
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()
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?
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)
-
- User
- Beiträge: 53
- Registriert: Freitag 7. Juli 2017, 12:35
Danke__deets__ hat geschrieben:Das erreichst du, indem du in deinem Fall die geteilte Datenstruktur an beide Instanzen uebergibst, statt ueber globale Variablen zu arbeiten.
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
@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.
-
- User
- Beiträge: 53
- Registriert: Freitag 7. Juli 2017, 12:35
Das dictionray könnte ungefähr so aussehen: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.
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.
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)?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.
Das Leben ist wie ein Tennisball.
-
- User
- Beiträge: 53
- Registriert: Freitag 7. Juli 2017, 12:35
Es soll schon so wie im ersten code beispiel laufen.EyDu hat geschrieben: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)?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.
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.