2010-11-17 26 views
3

這與我的另一個帖子multithreading issue with wx.TextCtrl (or underlying GTK+)有關,在主線程調用GUI交互後,我發現它又一次出現了管道塊緩衝問題。所以如何從subprocess.stdout獲得自發輸出?如何使用pexpect在Python中獲取子進程的自發輸出

簡而言之,目前我正在使用subprocess.popen來啓動外部長時間運行的程序。

launchcmd=["EXTERNAL_PROGRAM_EXE"] 
    p = subprocess.Popen(launchcmd, stdin=subprocess.PIPE, 
      stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    self.outputThread = BashProcessThread(p.stdout.readline) 
    self.outputThread.start() 
    # wx.TextCtrl is used to make input/output 
    self.textctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER|wx.TE_MULTILINE) 

我使用一個單獨的線程來讀取後臺程序的標準輸出,用「wx.CallAfter」回調。

class BashProcessThread(threading.Thread): 
    def __init__(self, readlineFunc, textctrl): 
     threading.Thread.__init__(self) 
     self.readlineFunc = readlineFunc 

    def run(self): 
     while True: 
      line = self.readlineFunc() 
      wx.CallAfter(textctrl.AppendText(line)) 

上面的代碼打印出子進程的日誌消息塊懸掛塊(而不是自發逐行),和最差的是剩餘的5-6線的日誌消息不能被及時打印,直到用戶發送下一個輸入。

從我以前的文章中,我知道有pty和pexpect,這可能會使子進程認爲它正在與僞tty進行交互。但是應該如何使用培訓,特別是考慮到後臺流程是長期的,獨立運行的任務?

例如,如果我用

child=pexpect.spawn(launchcmd) 

我怎樣才能得到子進程的輸出和輸入,所以我可以使用wx.TextCtrl打印輸出,並且還使用wx.TextCtrl轉發用戶輸入子進程?

回答

11

你有沒有嘗試過這樣的:

child = pexpect.spawn(launchcmd) 
while True: 
    try: 
     child.expect('\n') 
     print(child.before) 
    except pexpect.EOF: 
     break 
+0

我花了很長的30分鐘嘗試所有的產卵讀命令。從來沒有見過以前的財產。對你很重要。 – SuperFamousGuy 2012-12-07 17:22:19

+0

我認爲更優雅的解決方案是使用'child.logfile'屬性。 – wim 2012-12-10 01:00:21

0

我發現,這兩種方法用於獲取實時輸出工作。

如果您不希望用戶交互的選項,就像在一個後臺進程:如果你沒有使用一個後臺進程

child = pexpect.spawn(launchcmd) 
child.logfile = sys.stdout 
child.expect(pexpect.EOF) 
child.close() 

,並希望與該程序進行交互的能力(如果它提示你)。這裏發生的是你進入交互模式,pexpect直接寫入屏幕。當程序命中結束/ EOF時,會引發OSError。

child = pexpect.spawn(launchcmd) 
try: 
    child.interact() 
except OSError: 
    pass 
child.close()