2017-07-18 1 views
0

Dies funktioniert:subprocess.Popen funktioniert, aber jede Art von Warte (Anruf, warten, kommunizieren) verursacht „Reagiert nicht“

def letsExecute(): 
    import subprocess 
    subpr = subprocess.Popen("python " + codeFile + spacedout) 

Dies bewirkt, dass das Programm nicht reagiert (Ich bin auf Windows läuft):

def letsExecute(): 
    import subprocess 
    subprocess.call("python " + codeFile + spacedout) 

wait, communicate und im Grunde alles, was den Hauptprozess warten auf den Teilprozess macht bewirkt das gleiche. Ich möchte, dass der Hauptprozess beendet wird, wenn der Subprozess erfolgreich abgeschlossen wird.

Auch, zur Kenntnisnahme: diese Funktion ist an eine tkinter-Taste angeschlossen, und dieses Programm verwendet tkinter GUI und eine Hauptschleife(). Weiß nicht, ob sich das auf dieses Problem auswirkt, aber Sie trotzdem wissen zu lassen.

Vielen Dank im Voraus!

Antwort

1

Es gibt einige Probleme mit Ihrem Code.

subprocess.call()

die von args beschrieben Befehl ausführen. Warten Sie, bis der Befehl abgeschlossen ist, und geben Sie dann das Rückkehrcode-Attribut zurück.

wait() und communicate() sind auch blockierende Funktionen.

Verwenden Sie stattdessen poll().

subpr = subprocess.Popen(["python", codeFile, spacedout]) 

while subpr.poll() is None: 
    print("Still working...") 
    time.sleep(0.1) 

Da Sie das GUI-Thread zu reagieren möchten, können Sie den Sub-Prozess auf einem anderen Thread starten. so etwas wie dieses,

import subprocess 
import threading 
import time 

def letsExecute(): 
    t = threading.Thread(target=realExec) 
    t.run() 

def realExec(): 
    proc = subprocess.Popen(["python", codeFile, spacedout]) 

    while proc.poll() is None: 
     print("Still working...") 
     time.sleep(0.1) 
1

Zunächst einmal, warum Sie subprocess eine andere Python-Skript versuchen, wenn Sie können es einfach importieren?

Wie dem auch sei, Stengeln Sie Problem aus der Tatsache, dass jeder von call, wait und communicate wartet auf Beendigung des subprocess wenn timeout Parameter ommited wird. Aufgrund dieser tkinter Anwendung kann nicht aktualisiert werden und mainloop ist nicht erreichbar für Code-Flow.

Wenn Sie etwas kompliziert in Ihrem Kopf haben - werfen Sie einen Blick auf threading, multiprocessing und this Thema.

Wenn Sie nur den Hauptprozess beenden, wenn die subprocess beendet - einen Blick auf thoose Snippets:

test.py:

import time 

time.sleep(5) 

main.py:

try: 
    import tkinter as tk 
except ImportError: 
    import Tkinter as tk 

import subprocess 

class App(tk.Tk): 
    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 

     self.button = tk.Button(self, text='Start', command=self.start_test_process) 
     self.button.pack() 
     self.process = None 

    def continuous_check(self): 
     status = self.process.poll() 

     if status is None: 
      print('busy') 
      self.after(500, self.continuous_check) 
     elif status == 0: 
      print('successfully finished') 
      self.destroy() 
     else: 
      print('something went wrong') 

    def start_test_process(self): 
     self.process = subprocess.Popen('python test.py') 
     self.continuous_check() 


app = App() 
app.mainloop() 

Die Idee hier in halten mainloop erreichbar für Code mit Kombination von poll und after Methoden.

Verwandte Themen