2013-09-28 3 views
0

다음과 같은 UI를 구현해야합니다 : - "실험 1/X 실행"이라는 레이블이있는 윈도우와 버튼 - 창이로드되면 일부 실험이 시작됩니다. . 실험은 os.systemsubprocess.Popen으로 실행됩니다. 그냥 미리 컴파일 된 C++ 프로그램입니다. - 실험은 엄격히 하나씩 동시에 실행해야합니다 (따라서 subprocess.Popen을 사용할 수 없음). - 실험이 진행되는 동안 창을 활성화해야합니다. 실행 중이며 사용자가 버튼을 누를 수 있습니다. - 버튼을 누르면 실험이 중지되고 (현재 실험이 끝나고 중지 될 때까지 기다릴 수 있음) 창을 닫습니다. - 모든 실험이 끝나면 창이 닫히기 시작합니다.파이썬 : 서브 프로세스가있는 넌 모달 윈도우

처음에는 threading.Thread에서 실험을 시도했지만 여전히 창을 차단했습니다. Runner 객체가 하위 프로세스에 전달 될 절인해야한다 분명히 있기 때문에,

class StoppableProcess(Process): 
    def __init__(self, name, alg, proj, parent): 
     Process.__init__(self) 
     self.stop = False 
     self.name = name 
     self.alg = alg 
     self.proj = proj 
     self.parent = parent 

    def stop(self): 
     self.stop = True 

    def stopped(self): 
     return self.stop 

    def run(self): 
     count = len([k for k in self.proj.values()]) 
     i = 1 
     for p in self.proj.values(): 
      self.parent.label.setText("Running experiment " + str(i) + "/" + str(count)) 
      os.system("some command here") 
      i += 1 
      if self.stopped(): 
       break 
     self.parent.hide() 



class Runner(QDialog): 
    def __init__(self, parent): 
     QDialog.__init__(self, parent) 
     self.layout = QVBoxLayout() 
     self.label = QLabel("Running experiment 0/0") 
     self.setWindowTitle("Running experiments") 
     button = QPushButton("Break experiments") 
     self.layout.addWidget(self.label) 
     self.layout.addWidget(button) 
     self.setLayout(self.layout) 
     QObject.connect(button, SIGNAL("clicked()"), self.Break) 

    def Run(self, name, alg, proj): 
     self.thread = StoppableProcess(name, alg, proj, self) 
     self.thread.start() 
     self.show() 
     self.thread.join() 

    def Break(self): 
     self.thread.stop() 
     self.hide() 

그러나이 전혀 작동하지 않지만 산세가 실패 : 그래서 multiprocessing.Process로 전환. 나는 부모 인수를 피하고 대신 Qt 신호를 사용하는 것에 대해 생각하고 있었지만 더 나은 해결책이있을 수 있습니까?

답변

1

우선 백그라운드 프로세스를 시작하고 완료 될 때까지 subprocess.Popen을 실제로 사용할 수 있습니다. documentation, 특히 poll() 메소드를 참조하십시오. 프로세스가 종료 될 때까지 UI 이벤트 루프를 실행하십시오.

둘째로, 파이썬에서 스레드를 피하는 것이 좋습니다. 다중 처리 모듈은 Python으로 작성된 작업을 병렬 처리하려는 경우에 주로 유용합니다. IMO, 외부 자식 프로세스를 방금 시작하는 경우 하위 프로세스 모듈을 사용하는 것이 더 쉽다고 생각합니다.

experiments = [...] 
process = None 

def start_next_experiment(): 
    if not experiments: 
     print "Done!" 
    else: 
     experiment = experiments.pop() 
     process = subprocess.Popen(experiment) 

def on_start_clicked(): 
    start_next_experiment() 

def on_stop_clicked(): 
    # Clear the queue 
    experiments = [] 

    # optional: Kill the process 
    if process: 
     process.terminate() 

def on_idle(): 
    if process: 
     # use e.g. a PyQT timer to run this method periodically 
     process.poll() 
     if process.returncode is not None: 
      process = None 
      start_next_experiment() 
:

다음 의사는 아이디어를 보여

관련 문제