Seite 1 von 1

Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:13
von Europython
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!

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:22
von MagBen
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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:28
von Europython
Wie werte ich denn stdout und stderr aus ohne den Berechnungsprozess damit in den Vordergrund zu rücken?

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:37
von bwbg
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

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:38
von MagBen
Europython hat geschrieben:Wie werte ich denn stdout und stderr aus ohne den Berechnungsprozess damit in den Vordergrund zu rücken?
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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:43
von Europython
Mit "dateibasiert" meinst du, dass du es in eine Textdatei packst und die dann im anderen File ausliest?

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:45
von Sirius3
@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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:48
von MagBen
Europython hat geschrieben:Mit "dateibasiert" meinst du, dass du es in eine Textdatei packst und die dann im anderen File ausliest?
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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 14:52
von Europython
@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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 15:01
von MagBen
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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 15:26
von Sirius3
@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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 15:34
von 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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 15:50
von Europython
@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:

Code: Alles auswählen

Eingabe_PY = "python PyTest.py"
Popen(Eingabe_PY.split(), stdin = subprocess.PIPE)
Wenn ich das ganze mit Festlegung des Outputs starte, also:

Code: Alles auswählen

Eingabe_PY = "python PyTest.py"
Popen(Eingabe_PY.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin = subprocess.PIPE)
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...

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 16:35
von 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.

Re: Interprocessing zweier Python-Skripte

Verfasst: Dienstag 28. Oktober 2014, 17:31
von pillmuncher
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?
Gar nicht. Du hast ein falsches Bild davon im Kopf, wie diese Dinge zusammenhängen.

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 + 1
Diese speicherst du in einer Datei namens (zB.) comp.py. Damit hast du ein Modul erstellt, das eine wiederverwendbare Funktion enthält.

Nun 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)))
Das speicherst du im selben Verzeichnis wie das Modul oben unter dem Namen cli.py ab. Dann kannst du es so verwenden:

Code: Alles auswählen

$ python cli.py 123
247
Und nun möchtest du noch eine GUI für die Berechnung haben:

Code: 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()
Das speicherst du, wieder im selben Verzeichnis, als gui.py ab. Wenn du dann

Code: Alles auswählen

$ python gui.py
aufrufst, geht ein kleines Fenster mit einem Textfeld und einem Button auf, und wenn du eine Zahl eingibst und den Button drückst, geht eine Message Box mit dem Ergebnis auf.

Wie du siehst, musst du nirgends "Werte/Einstellungen an das Berechnungs-file übertragen", sonder nur Funktionen importieren und verwenden.