2013-12-19 23 views
3

我在Windows上有一個程序,調用一堆子進程,並在GUI中顯示結果。我使用PyQt作爲GUI,並使用subprocess模塊來運行程序。當子進程在Python中運行時,如何從子進程PIPE獲取數據?

我有以下WorkerThread,即產生一個子線程用於專門讀取過程標準輸出和打印結果中的每個shell命令(以後我會給你電匯它的GUI)。

這一切正常。 除了proc.stdout.read(1)從不返回,直到子流程完成後。這是一個很大的問題,因爲其中一些子進程可能需要15-20分鐘才能運行,並且我需要在運行時顯示結果。

在子流程運行時,我需要做些什麼來使管道工作?

class WorkerThread(QtCore.QThread): 
    def run(self): 
     def sh(cmd, cwd = None): 
      proc = subprocess.Popen(cmd, 
            shell = True, 
            stdout = subprocess.PIPE, 
            stderr = subprocess.STDOUT, 
            stdin = subprocess.PIPE, 
            cwd = cwd, 
            env = os.environ) 

      proc.stdin.close() 

      class ReadStdOutThread(QtCore.QThread): 
       def run(_self): 
        s = '' 
        while True: 
         if self.request_exit: return 

         b = proc.stdout.read(1) 
         if b == '\n': 
          print s 
          s = '' 
          continue 

         if b: 
          s += b 
          continue 

         if s: print s 
         return 

      thread = ReadStdOutThread() 
      thread.start() 

      retcode = proc.wait() 
      if retcode: 
       raise subprocess.CalledProcessError(retcode, cmd) 

      return 0 

FWIW:我重寫使用QProcess整個事情,我看到完全相同的問題。 stdout收到沒有數據,直到基礎過程已返回。然後,我立即得到一切。

回答

1

如果您知道命令行輸出多長時間,您可以輪詢該進程的stdout PIPE。

我的意思的例子:

import select 
import subprocess 
import threading 
import os 

# Some time consuming command. 
command = 'while [ 1 ]; do sleep 1; echo "Testing"; done' 

# A worker thread, not as complex as yours, just to show my point. 
class Worker(threading.Thread): 

    def __init__(self): 
     super(Worker, self).__init__() 
     self.proc = subprocess.Popen(
      command, shell=True, 
      stdout=subprocess.PIPE, 
      stdin=subprocess.PIPE, stderr=subprocess.STDOUT 
     ) 

    def run(self): 
     self.proc.communicate() 


    def get_proc(self): 
     # The proc is needed for ask him for his 
     # output file descriptor later. 
     return self.proc 


if __name__ == '__main__': 
    w = Worker() 
    w.start() 

    proc = w.get_proc() 

    pollin = select.poll() 

    pollin.register(proc.stdout, select.POLLIN) 


    while (1): 
     events = pollin.poll() 
     for fd, event in events: 
      if event == select.POLLIN: 
       # This is the main issue of my idea, 
       # if you don't know the length of lines 
       # that process ouput, this is a problem. 
       # I put 7 since I know the word "Testing" have 
       # 7 characters. 
       print os.read(fd, 7) 

也許這不正是你要尋找的,但我認爲它給你怎樣做才能解決您的問題一個不錯的主意。

編輯:我想我剛剛找到了你需要的東西Streaming stdout from a Python subprocess in Python

+0

我不知道輸出會有多長時間。 –

+0

@ChrisB。我剛剛添加了一個可能是你正在尋找的例子的鏈接。 –

相關問題