2009-07-14 599 views
7

我在Windows上使用python 2.5。我希望通過Popen與控制檯進程交互。我目前有這一小段代碼:通過Python與Windows控制檯應用程序交互

p = Popen(["console_app.exe"], stdin=PIPE, stdout=PIPE) 
# issue command 1... 
p.stdin.write('command1\n') 
result1 = p.stdout.read() # <---- we never return here 
# issue command 2... 
p.stdin.write('command2\n') 
result2 = p.stdout.read() 

我可以寫入標準輸入但無法讀取標準輸出。我錯過了一個步驟?我不想使用p.communicate(「command」)[0],因爲它終止了進程,我需要隨着時間的推移動態地與進程交互。

在此先感謝。

+0

您的代碼似乎是正確的。從控制檯執行時,console_app是否正常工作?它爲command1返回什麼? – luc 2009-07-14 13:04:21

+0

yes console_app在cmd.exe中運行時正常工作它只是根據提供的輸入(有時是字符串)輸出一些數字 – QAZ 2009-07-14 13:13:41

回答

0

我想你可能想嘗試使用readline()來代替?

編輯:對不起,誤會。可能this問題可以幫到你嗎?

+0

readline()也掛起。我可以確認控制檯應用程序輸出的數據應該在Python端正確讀入。 – QAZ 2009-07-14 11:56:13

0

控制檯應用程序是否有可能以某種方式緩衝其輸出,以便在管道關閉時僅將其發送到標準輸出?如果您有權訪問控制檯應用程序的代碼,也許在一批輸出數據可能有幫助後插入一次沖洗?

或者,它是否實際寫入stderr而不是stdout出於某種原因?

只是再次查看您的代碼並想到其他事情,我看到您正在發送「command \ n」。控制檯應用程序可以簡單地等待一個回車符而不是一個新行嗎?也許控制檯應用程序正在等待您在生成任何輸出之前提交命令。

+0

謝謝,很好的建議。我不幸的是無法訪問控制檯應用程序的源代碼。確認其寫作stdout而不是stderr。 – QAZ 2009-07-14 12:21:02

0

這裏有完全相同的問題。我鑽進DrPython源代碼,並偷走了wx.Execute()解決方案,它工作正常,特別是如果您的腳本已經在使用wx。我從來沒有在Windows平臺上找到正確的解決方案,但...

7

您的問題在於您正在嘗試控制一個交互式應用程序。

stdout.read()將繼續讀取,直到它到達流,文件或管道的末尾。不幸的是,如果是交互式程序,管道只有在程序退出時才關閉;如果您發送的命令不是"quit"以外的其他命令,則永遠不會。

您將不得不恢復爲使用stdout.readline()逐行讀取子進程的輸出,並且您最好有一種方法來告訴程序何時準備好接受命令,以及何時發出命令到程序完成,你可以提供一個新的。在像cmd.exe這樣的程序的情況下,即使readline()也不能滿足,因爲指示可以發送新命令的行不會被換行符終止,因此必須逐字節地分析輸出。下面是運行cmd.exe一個示例腳本,找提示,然後發出dir然後一個exit

from subprocess import * 
import re 

class InteractiveCommand: 
    def __init__(self, process, prompt): 
     self.process = process 
     self.prompt = prompt 
     self.output = "" 
     self.wait_for_prompt() 

    def wait_for_prompt(self): 
     while not self.prompt.search(self.output): 
      c = self.process.stdout.read(1) 
      if c == "": 
       break 
      self.output += c 

     # Now we're at a prompt; clear the output buffer and return its contents 
     tmp = self.output 
     self.output = "" 
     return tmp 

    def command(self, command): 
     self.process.stdin.write(command + "\n") 
     return self.wait_for_prompt() 

p  = Popen(["cmd.exe"], stdin=PIPE, stdout=PIPE) 
prompt = re.compile(r"^C:\\.*>", re.M) 
cmd = InteractiveCommand(p, prompt) 

listing = cmd.command("dir") 
cmd.command("exit") 

print listing 

如果時間不是重要的,並且不需要交互的用戶,也可以是很簡單,只是爲了批量調用:

from subprocess import * 

p = Popen(["cmd.exe"], stdin=PIPE, stdout=PIPE) 
p.stdin.write("dir\n") 
p.stdin.write("exit\n") 

print p.stdout.read() 
2

您是否試圖強制Windows結束行? 即

p.stdin.write('command1 \r\n') 
p.stdout.readline() 

UPDATE:

我剛剛檢查了Windows CMD.EXE的解決方案,並與工作的ReadLine()。但它有一個問題Popen的stdout.readline 。因此,如果應用程序會返回一些沒有結束的內容,那麼您的應用程序將永久停留。

但有一個變通對於檢查出:http://code.activestate.com/recipes/440554/

相關問題