Schleife nach Beendigung von externem Prozess

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Mattversuchts
User
Beiträge: 22
Registriert: Dienstag 4. September 2012, 09:34

Hallo,

ich habe aktuell folgendes Problem:
Ich möchte einen Parametervariation eines externen Prozess ausführen, der sich seine Informationen aus einer .txt zieht.
Wie ich die Schleife aufbaue ist klar. Nur der Prozess hat eine Laufzeit von ungefähr einer halben Stunde. Und dieses Programm, dass im Hintergrund läuft, darf immer nur einmal gleichzeitig ausgeführt werden.

Gibt es eine Möglichkeit den Prozess zu überwachen? Bzw auszugeben wann dieser abgeschlossen ist? :K

Vielen Dank im Voraus

Matt
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Externes Kommando? Subprocess.
Dazu gibt es hier ganz viele Threads und auch eine tolle Dokumentation: http://docs.python.org/library/subprocess.html
Mattversuchts
User
Beiträge: 22
Registriert: Dienstag 4. September 2012, 09:34

Vielen Dank für die Antwort.
Ich hab mich jetzt die letzten Wochen eingearbeitet. Dennoch komm ich nicht wirklich weiter...

Code: Alles auswählen

p = subprocess.Popen(["C:\Programm\Blub.exe", os.path.join("Y:\Dings", "dings.abc")], stdout=subprocess.PIPE)
                                time.sleep(3)
                                SendKeys("{F8}")
                                time.sleep(10)
Das Problem:

Das Programm startet...
Mit dem drücken von "F8" öffnet der Subprocess wiederrum ein child...
Ist das Child durchgelaufen (ca. 10 min) popt ein Fenster auf, dass mit Enter bestätigt werden muss. Anschließend müsste ich den kompletten subprocess schließen...

Von einem Kollegen hab ich den Tipp bekommen, dass ich /n und /h für hide und schließen verwenden soll... das hilft mir allerdings nicht wirklich weiter...

Wie könnte ich das lösen? Komme irgendwie gar nichtmehr weiter...
deets

Ersmal ein Tipp: irgendwann beginnt eines deiner Verzeichnisse mit einem n oder t, und du wirst mit der Art, wie du Pfade angibst (nur ein Backslash in einem un-escapeten String) maechtig auf die Nase fallen. Benutz entweder Vorwaertsslashes (Windows schluckt die), raw-strings, oder konsequenter os.path.join.

Und zu deinem Problem: warum musst du den Subprocess "schliessen"? Wenn das Kind durchgelaufen ist, dann ist der Subprocess tot. Du kannst seinen Status abfragen.

Und "/n" bzw "/h" sind wohl Argumente fuer as Blub.exe - was wahrscheinlich nicht Blub.exe heisst, sondern irgendwie anders, und ob und welche Argumente es so alles schluckt, und was die dann tun, und ob es Fenster aufmacht, oder oder oder... koennen wir alles nicht wissen. Denn wir kennen es ja nicht.
Mattversuchts
User
Beiträge: 22
Registriert: Dienstag 4. September 2012, 09:34

Danke für die Antwort :wink:
Danke für den ersten Hinweis...! werd ich mir zu Herzen nehmen...

Wenn ich aber exakt weiß, dass es einen bestimmten Ablauf hat: (es ist 250 mal das gleiche direkt hintereinander)
Gibt es nicht eine Möglichkeit es dennoch zu beeinflussen? :K
deets

Nochmal: wir wissen nicht, was 'es' ist. Also wissen wir auch nicht, wie 'es' beeinflussbar ist.

Ausser dem, was subprocess generell anbietet, wie den Zustand des Programmes zu erfragen (laeuft es noch oder nicht, und wenn nicht, ist es normal oder abnormal beendet).

Wie waere es, wenn du mal in klaren Worten beschreibst, was dein Programm macht, und was Blub.exe macht, und was das alles zusammen machen soll.
Mattversuchts
User
Beiträge: 22
Registriert: Dienstag 4. September 2012, 09:34

:oops:

klar.

Also:
Ich führe eine Parametervaration mit Hilfe eines Simulationsprogramms durch.
Das Simulationsprogramm nimmt sich eine Input File; liest die InputFile; startet eine Simulation und gibt die Werte in eine Externe Datei aus.

Parametervariation, InputFile, Auslesen der Daten hab ich abgeschlossen und laufen auch.

Das Problem:
Der Start der Simulation das Erkennen des Endes der Simulation und das Schließen des Simulationsprogramms.

Soo:

Ich weiß wie ich das Simulationsprogramm mit dem zugehörigen InputFile öffnen kann:

Code: Alles auswählen

p = subprocess.Popen(["C:\Programm\Blub.exe", os.path.join("Y:\Dings", "dings.abc")], stdout=subprocess.PIPE)
mit

Code: Alles auswählen

time.sleep(3)
Will ich sicherstellen, dass das Simulationsprogramm auch wirklich geöffnet hat

Mit SendKeys gebe ich den Kurzbefehl um die Simulation zu starten

Code: Alles auswählen

SendKeys("{F8}")
Jetzt kommt das Problem:
Mit dem Start der Simulation öffnet sich ein Child (ein neues Fenster/die Simulation selbst) diese läuft unterschiedlich lang (ca. 10 min).

Wenn die Simulation abgeschlossen ist erscheint ein Eingabebefehl, der mit Enter bestätigt werden muss. Das Child schließt sich damit automatisch.
Ist die Simulation beendet möchte ich das Simulationsprogramm komplett schließen.

Das Problem: Ab dem Start der Simulation weiß ich nicht mehr weiter.
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Das geht über die Fähigkeiten von subprocess hinaus. Ich habe dir in einem anderen Thread schon einmal pywinauto empfohlen, damit lassen sich GUI-Anwendungen recht gut fernsteuern. Unter anderem kannst du prüfen, ob ein bestimmtes "Fenster" bereits aufgetaucht ist.
Mattversuchts
User
Beiträge: 22
Registriert: Dienstag 4. September 2012, 09:34

Vielen Dank!

Hat super geklappt!!

:)
Mattversuchts
User
Beiträge: 22
Registriert: Dienstag 4. September 2012, 09:34

Hey Leute,
Ich hänge seit Tagen an folgendem Problem
der aktuelle stand:

Code: Alles auswählen

x = 0
for wert1 in xrange(20, 70, 5):
        for Wert2 in xrange(5,15, 1):
                x = x+1
                def timeout_handler(timeout=2500):
                        timer = threading.Timer(timeout, timeout_handler)
                        timer.start()
                        if x > 1 and p.poll() == None or 0:
                                p.kill()
                timeout_handler()                
                while True:

                        time.sleep(30)
        
                        p = subprocess.Popen(["C:\Programm\Blub.exe",os.path.join("Y:\Pfad", "XY.ab")], stdout=None)
                        time.sleep(5)


                        p.wait()
                        break

#Folgeprozess
Das Problem ist: ich möchte mit der while-Schleife kontrollieren, ob der Subprocess noch offen ist.
Ist es abgeschmiert möchte ich nach der abgelaufenen Zeit hier 2500 Sec das ganze Neustarten.
Ist p durchgelaufen gibt es ein Folgeprozess, der das ganze auswertet. Wert1 und Wert2 werden bei jedem Durchgang geändert und für p benötigt.
Das Teil läuft so auch... Nur nach einer gewissen Zeit wird p nichtmehr geschlossen. Oder Schließt sich von selbst automatisch...
Hättet ihr einen Hinweis für mich woran das liegen könnte?

Grüße
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Das sieht ein bisschen seltsam aus. Du startest den Timer, der den Prozess killen soll, bevor der Prozess da ist, dann wartest du nochmal 30 Sekunden bevor du ihn startest und anschließend nochmal 5 Sekunden bevor du auf sein Ende wartest? Vor allem sehe ich nicht, dass du den Timer stoppst, wenn der Prozess doch durchgelaufen ist, etc.

Das erste Ergebnis beim Suchen nachh "python subprocess timemout" war das hier, und das müsste problemlos funktionieren.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Mattversuchts hat geschrieben:

Code: Alles auswählen

x = 0
for wert1 in xrange(20, 70, 5):
        for Wert2 in xrange(5,15, 1):
                x = x+1
                def timeout_handler(timeout=2500):
                        timer = threading.Timer(timeout, timeout_handler)
                        timer.start()
                        if x > 1 and p.poll() == None or 0:
                                p.kill()
                timeout_handler()                
                while True:

                        time.sleep(30)
        
                        p = subprocess.Popen(["C:\Programm\Blub.exe",os.path.join("Y:\Pfad", "XY.ab")], stdout=None)
                        time.sleep(5)


                        p.wait()
                        break

#Folgeprozess
Dazu gibt es einiges zu sagen:

- Bitte jeweils 4 spaces einrücken, nicht 8. Siehe PEP8.

- p.poll() == None or 0 macht nicht, was du denkst, dass es macht. Es ist äquivalent zu (p.poll() == None) or 0. Was du statt dessen möchtest, ist lediglich p.poll() is None, siehe auch hierzu PEP8.

- eine Endlos-while-Schleife, bei der immer am Ende des ersten Durchlaufs ein break ausgeführt wird, wird genau 1x ausgeführt. Was ist dabei der Vorteil ggü. dem, die Schleife einfach wegzulassen?

- timeout_handler() wird in timeout_handler() selbst mittels threading.Timer(timeout, timeout_handler) gestartet... WTF?

- das x ist lediglich eine krude und uneffektive Art, ein Latch zu simulieren. Es tut zudem nicht, was du möchtest, dass es tut. Es ist zB. möglich, dass zwischen dem Aufruf von p.poll() und dem von p.kill() p bereits an einen neuen Prozess gebunden wurde, so dass du dann den neuen Prozess abschießt, weil der alte noch läuft. Oder auch nicht, da ja im main thread mittels p.wait() gewartet wird, bis der Prozess beendet wurde, und erst danach ein neuer Prozess gestartet wird. Wozu dann aber die komplizierte Timer-Konstruktion?

- Wert1 und Wert2 werden entgegen deiner Aussage im Code nirgends verwendet. Siehe hierzu http://sscce.org.

Versuch es statt dessen mal hiermit:

Code: Alles auswählen

import subprocess
import time

for wert1 in xrange(20, 70, 5):
    for wert2 in xrange(5, 15, 1):
        p = subprocess.Popen(
            ['C:/Programm/Blub.exe', os.path.join('Y:', 'Pfad', 'XY.ab')], stdout=None)
        # alle 5 sec nachsehen, ob p schon beendet wurde.
        for i in xrange(0, 2500, 5):
            time.sleep(5)
            if p.poll() is not None:
                break
        else:  # nach 2500 sec immer noch nicht? ==> aufgeben.
            p.kill()
Da ich keine Blub.exe besitze, habe ich es mit einem anderen Program (und kürzeren Zeiten) ausprobiert.
Und ja, das else gehört wirklich zum for, und nicht zum if.
In specifications, Murphy's Law supersedes Ohm's.
Mattversuchts
User
Beiträge: 22
Registriert: Dienstag 4. September 2012, 09:34

Hey,
super...! echt vielen vielen Dank für die investierte Zeit...
Du hast mir echt super weitergeholfen und viele Anregungen für die nächsten Projekte gegeben...

Das echt super nett von dir!
:) :)


Danke :)
Antworten