Hallo zusammen,
ich versuche mich nun seit zwei Tagen an der Verknüpfung zweier Python-files zum Übergeben von Variablen.
Beim einen Skript handelt es sich um das Erstellen einer GUI mittels gtk wobei vom Benutzer diverse Dinge festgelegt werden können, zum Beispiel mit welcher Berechnungsmethode im zweiten Skript gearbeitet werden soll, welche Datei (Pfad) als Basis für die Berechnung eingelesen werden soll, etc.
In der Benutzeroberfläche soll außerdem eine ProgressBar angezeigt werden und es sollen Buttons zum Pausieren und Beenden der Berechnung, also des zweiten Skriptes zur Verfügung stehen. Demnach brauche ich ja auch Output vom rechnenden Python-Skript.
Dennoch soll nach wie vor in der Benutzeroberfläche gearbeitet werden können (eben um zum Beispiel auf Pause zu drücken), weshalb das zweite Skript im Hintergrund ausgeführt werden soll. Außerdem habe ich das berechnende Skript über subprocess gestartet, jedoch ohne Festlegung des Outputs, da die Berechnung sonst nicht im Hintergrund stattfindet.
So viel zunächst einmal zu den Randbedingungen.
Ich hatte mich jetzt erst einmal an Sockets probiert, komme mit denen aber nicht weiter, da ich dann jedes mal im Verbindungsaufbau hängen bleibe (?!). Habt ihr mir eine Idee, bzw. einen Rat womit so etwas am besten/ehesten umgesetzt werden kann? Ich hoffe der Sachverhalt ist soweit verständlich dargestellt, anderenfalls versuche ich es an gegebener Stelle zu konkretisieren.
Vielen Dank im Voraus!
Interprocessing zweier Python-Skripte
Die GUI könnte die Rechnung mit subprocess.Popen starten und dann stdout und stderr vom Berechnungsprozess auswerten. Pause könntest Du über stdin realisieren.
-
Europython
- User
- Beiträge: 16
- Registriert: Samstag 11. Oktober 2014, 12:40
Wie werte ich denn stdout und stderr aus ohne den Berechnungsprozess damit in den Vordergrund zu rücken?
Oder Du importierst dein Berechnungsmodul in Dein GUI-Modul und führst die Berechnungen als API-Zugriff aus. Dies setzt natürlich eine entsprechende Code-Struktur voraus.
Grüße ... bwbg
Grüße ... bwbg
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Ich mache sowas Dateibasiert. Das hat dann eine gewisse Trägheit, aber wenn die Berechnungen sehr lange laufen, dann kommt es darauf nicht an. Außerdem sind GUI und Berechnung dann schön voneinander entkoppelt.Europython hat geschrieben:Wie werte ich denn stdout und stderr aus ohne den Berechnungsprozess damit in den Vordergrund zu rücken?
-
Europython
- User
- Beiträge: 16
- Registriert: Samstag 11. Oktober 2014, 12:40
Mit "dateibasiert" meinst du, dass du es in eine Textdatei packst und die dann im anderen File ausliest?
@Europython: man sollte nicht zu viel Kommunikation über stdin/stdout abwickeln. Das macht das ganze nur unwartbar kompliziert. Warum willst Du die Berechnung ein einem eigenständigen Programm ablaufen lassen, wenn Du gleichzeitig eine so enge Kommunikation brauchst?
Um Prozesse anzuhalten und fortzusetzen gibt es die Unix-Signale SIGSTOP und SIGCONT. Das funktioniert ohne dass der eigentliche Rechenprozess angepasst werden muß.
Ansonsten sind für verteiltes Rechnen Messagebroker ganz praktisch, das sind Server, die den Austausch von Nachrichten zwischen Prozessen (auch über Rechnergrenzen hinweg) regeln.
Um Prozesse anzuhalten und fortzusetzen gibt es die Unix-Signale SIGSTOP und SIGCONT. Das funktioniert ohne dass der eigentliche Rechenprozess angepasst werden muß.
Ansonsten sind für verteiltes Rechnen Messagebroker ganz praktisch, das sind Server, die den Austausch von Nachrichten zwischen Prozessen (auch über Rechnergrenzen hinweg) regeln.
Ja, das funktioniert dann auch, wenn GUI und Berechnung auf unterschiedlichen Rechnern mit unterschiedlichen OS laufen und das Rechenprogramm braucht auch nicht in Python entwickelt zu sein.Europython hat geschrieben:Mit "dateibasiert" meinst du, dass du es in eine Textdatei packst und die dann im anderen File ausliest?
-
Europython
- User
- Beiträge: 16
- Registriert: Samstag 11. Oktober 2014, 12:40
@Sirius3: Ich möchte die Berechnung auch per batch mode ermöglichen, daher sollte ich das getrennt aufbauen, oder täusche ich mich da?
@MagBen: Okay, das hatte ich mir auch schon überlegt, wollte ich aber eigentlich vermeiden, da ich möglichst wenig extra-Textfiles verwenden wollte.
@MagBen: Okay, das hatte ich mir auch schon überlegt, wollte ich aber eigentlich vermeiden, da ich möglichst wenig extra-Textfiles verwenden wollte.
Die Berechnung würde ich nicht in eine GUI integrieren. Die GUI sollte ein Anhängsel der Berechnung sein und nicht umgekehrt. Das ist wie bei einem Rennwagen, erst kommt der Motor und das Fahrgestell und daran wird das Amaturenbrett gehängt und nicht umgekehrt.
@MagBen: ich glaube niemand möchte hier GUI und Berechnung vermischen. Europython hat ja die Berechnungen schon separat.
@Europython: GUI und Batch können sich die Module zur Berechnung teilen. Die Batch-Main parst halt Kommandozeilen-Parameter und ruft damit die Rechnung auf, die GUI "parst" dagegen irgendwelche Formulareingabefelder und ruft damit die Rechnung auf.
@Europython: GUI und Batch können sich die Module zur Berechnung teilen. Die Batch-Main parst halt Kommandozeilen-Parameter und ruft damit die Rechnung auf, die GUI "parst" dagegen irgendwelche Formulareingabefelder und ruft damit die Rechnung auf.
-
BlackJack
@Europython: Du kannst das mit der Berechnung ja getrennt entwickeln, aber halt so das man es in einer GUI-Anwendung importieren und benutzen kann. Das schliesst sich ja nicht gegenseitig aus. Im Idealfall trennt man das so das man die Programmlogik so getrennt hat, dass sowohl Text- oder Kommandozeilen-„Oberfläche” als auch GUI getrennt sind und die von beiden unabhängige Programmlogik benutzen.
Ich verstehe nicht so recht was Du damit meinst dass Du die Berechnung in den „Vordergrund” holen musst wenn Du die Ausgaben verarbeiten willst!? Du müsstest das in einer GUI-Anwendung zumindest nebenläufig machen, weil ja sowohl Berechnung als auch GUI gleichzeitig bearbeiten werden müssen.
Aber wie Sirius3 schon schrieb, ist diese Kommunikation über die Streams nichts so schön. Man muss dann auf der einen Seite Sachen in einem bestimmten Format schreiben, die man dann auf der anderen parsen muss. Wenn das in *einem* Prozess läuft, spart man sich das.
Ich verstehe nicht so recht was Du damit meinst dass Du die Berechnung in den „Vordergrund” holen musst wenn Du die Ausgaben verarbeiten willst!? Du müsstest das in einer GUI-Anwendung zumindest nebenläufig machen, weil ja sowohl Berechnung als auch GUI gleichzeitig bearbeiten werden müssen.
Aber wie Sirius3 schon schrieb, ist diese Kommunikation über die Streams nichts so schön. Man muss dann auf der einen Seite Sachen in einem bestimmten Format schreiben, die man dann auf der anderen parsen muss. Wenn das in *einem* Prozess läuft, spart man sich das.
-
Europython
- User
- Beiträge: 16
- Registriert: Samstag 11. Oktober 2014, 12:40
@Sirius3: Okay, das macht für mich Sinn. Danke für die Erklärung!
@BlackJack: Ich starte die Berechnung ja wie erwähnt über Popen:
Wenn ich das ganze mit Festlegung des Outputs starte, also:
dann kann ich in der GUI nichts mehr machen...
Ich bin leider blutiger Anfänger und habe etwas Probleme mich mit dem ganzen vertraut zu machen...
Nochmal zurück zum Thema Variablenübergabe. Wie kann ich denn z.B. in der GUI festgelegte Werte/Einstellungen an das Berechnungs-file übertragen? Das krieg ich einfach ums Verrecken nicht hin...
@BlackJack: Ich starte die Berechnung ja wie erwähnt über Popen:
Code: Alles auswählen
Eingabe_PY = "python PyTest.py"
Popen(Eingabe_PY.split(), stdin = subprocess.PIPE)Code: Alles auswählen
Eingabe_PY = "python PyTest.py"
Popen(Eingabe_PY.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin = subprocess.PIPE)Ich bin leider blutiger Anfänger und habe etwas Probleme mich mit dem ganzen vertraut zu machen...
Nochmal zurück zum Thema Variablenübergabe. Wie kann ich denn z.B. in der GUI festgelegte Werte/Einstellungen an das Berechnungs-file übertragen? Das krieg ich einfach ums Verrecken nicht hin...
-
BlackJack
@Europython: Wenn das Berechnungscript als eigenes Programm läuft bekommt man da Werte über die Kommandozeile, die Standardeingabe, oder Dateien hinein. Auch in Kombinationen. Besser wäre es aber wie gesagt wenn man den Berechnungscode direkt benutzt. Für die Verarbeitung von Argumenten und Optionen die auf der Kommandozeile übergeben werden gibt es in der Standardbibliothek das `argparse`-Modul. Für Daten die über die Standardeingabe oder aus Dateien gelesen werden, sollte man ein passendes Dateiformat wählen. JSON bietet sich oft an, da gibt es in der Standardbibliothek auch ein Modul für: `json`.
Wenn Du die Standard(fehler)ausgabe des externen Prozesses umlenkst und der dort auch etwas ausgibt, dann musst Du das natürlich auslesen, sonst blockiert der externe Prozess beim Ausgeben von weiteren Informationen weil der Ausgabepuffer voll ist. Das müsste innerhalb einer GUI in einem eigenen Thread passieren und dann muss man die Mittel die das jeweilige GUI-Toolkit bereit stellt nutzen um das dann Threadsafe irgendwie in die Anzeige zu bekommen.
Wenn Du die Standard(fehler)ausgabe des externen Prozesses umlenkst und der dort auch etwas ausgibt, dann musst Du das natürlich auslesen, sonst blockiert der externe Prozess beim Ausgeben von weiteren Informationen weil der Ausgabepuffer voll ist. Das müsste innerhalb einer GUI in einem eigenen Thread passieren und dann muss man die Mittel die das jeweilige GUI-Toolkit bereit stellt nutzen um das dann Threadsafe irgendwie in die Anzeige zu bekommen.
- pillmuncher
- User
- Beiträge: 1532
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Gar nicht. Du hast ein falsches Bild davon im Kopf, wie diese Dinge zusammenhängen.Europython hat geschrieben:Nochmal zurück zum Thema Variablenübergabe. Wie kann ich denn z.B. in der GUI festgelegte Werte/Einstellungen an das Berechnungs-file übertragen?
Hier mal anders: angenommen, du willst immer wieder eine Berechnung durchführen, sagen wir x * 2 + 1 für wechselnde x. Dann schreibst du dir eine Funktion:
Code: Alles auswählen
def important_computation(x):
return x * 2 + 1Nun möchtest du ein Kommandozeileninterface (cli) dafür, damit du die Berechnung aus der Shell heraus aufrufen kannst. Dazu schreibst du ein Programm, welches das Modul oben importiert und die darin stehende Funktion verwendet:
Code: Alles auswählen
import comp # das Modul comp wird durch die Datei comp.py definiert
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("n")
args = parser.parse_args()
print(comp.important_computation(int(args.n)))Code: Alles auswählen
$ python cli.py 123
247Code: Alles auswählen
import comp
import tkinter as tk
import tkinter.messagebox as msgbox
class App(tk.Tk):
def __init__(self):
super().__init__()
self.entry = tk.Entry()
self.entry.pack()
self.button = tk.Button(self, text = 'Press', command=self.compute)
self.button.pack()
def compute(self):
msg = str(comp.important_computation(int(self.entry.get())))
msgbox.showinfo(message=msg)
App().mainloop()Code: Alles auswählen
$ python gui.pyWie du siehst, musst du nirgends "Werte/Einstellungen an das Berechnungs-file übertragen", sonder nur Funktionen importieren und verwenden.
In specifications, Murphy's Law supersedes Ohm's.
