2010-10-13 107 views
2

我有一個名爲pregeocode的窗口應用程序(我們缺乏源代碼),這個程序基本上將地理編碼寫入輸入文件。除非出現錯誤,否則該程序實際上不會寫入任何內容。這個程序通常是從一個小的Python程序中調用的(它處理參數等,並進行所有有趣的預處理)。捕獲未寫入標準輸出stderr的控制檯輸出?

我們通過查看輸出文件是否實際創建(無論如何總是返回0)來檢查它是否失敗。但是,如果子進程失敗,則表明沒有任何內容打印到stderr或stdout。 (它成功地處理了大約100個左右,但只有一個單獨的一個很糟糕,但我希望能夠看到是什麼原因導致錯誤)

小python腳本通過subprocess.Popen調用應用程序:

argslist = [r'C:\workspace\apps\pregeocode.exe', '-in', inputfilename, '-out', outputfilename, '-gcp', gcp_file] 
p = subprocess.Popen(argslist, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 
print str(p.communicate()) 

給出的輸出:

('', '') 

但是如果我使用通過CMD相同的參數手動運行該程序,我得到的輸出:

45 IMAGE_EXTENT_TOO_SMALL 

(周圍有60多不同的錯誤信息,45是錯誤編號)

使用shell = True參數不會改變任何東西,我也可以在網上找到任何有關這個問題。實際的exe是很久以前在內部製作的東西,我們缺乏它的源代碼,所以我看不出它是如何打印出來的。

那麼,爲什麼不能subprocess實際捕獲這個stdout或stderr?

編輯

os.system(" ".join(argslist)) 

正確打印錯誤消息:

45 IMAGE_EXTENT_TOO_SMALL 

EDIT 2

原來的應用程序使用ERDAS的工具包。他們的工具包將所有stdout/stderr重定向到它們的日誌子系統。日誌子系統然後通過「CON」重寫它。

+0

當你用'2> out.err'從cmd運行它時會發生什麼? out.err是否以文本結束? – 2010-10-13 18:51:57

+0

是的,它正確打印出消息。 – UberJumper 2010-10-13 18:52:46

+0

可以肯定的是,「打印出來」的意思是「把它放在文件中」,對吧?它不顯示在屏幕上。 – 2010-10-13 18:57:52

回答

5

由於錯誤消息真的不來了在任一stdout也不stderr,我最好的猜測是,該程序正在使用Windows的等效斷開/dev/tty的,不管它是什麼。在Unix中,你可以小心使用pty.openpty來攔截,但據我所知,在Python中不支持類似的Windows特定技巧。您可以嘗試使用Expect for Windows

+0

我和Zack在一起。 Windows可執行文件可以執行幾項*看起來像寫入到stdio,但不是真的。對於Windows而言,期望有助於幫助(即在某些情況下),但並非總是如此(從這個意義上來說,Expect-for-Windows不是通用的)。 – 2010-10-13 19:02:17

+0

有一點要嘗試的是獲得一個Windows API間諜,看看你是否可以挑選出它在做什麼。像http://www.apimonitor.com/ – 2010-10-13 19:54:14

+0

看起來很好看,它不是我所希望的。我想我只是不得不放手。原來ERDAS將所有stdout/stderr重定向到它們的日誌子系統。這個日誌子系統然後將輸出重定向到「CON」,我不認爲有一種方法來捕獲這個輸出,所以我想我幾乎在這裏輸了。 – UberJumper 2010-10-13 19:54:58

0

你使用python 2.5還是2.6的早期版本? 你可以試試這個子過程。與標準錯誤重定向check_output到stdout:

out_err = subprocess.check_output(argslist, stderr=subprocess.STDOUT) 

如果out_err得到兩個輸出和錯誤,你可能需要重定向輸出和錯誤到文件的對象,後來從這些文件中的對象讀取(因爲Windows不具備UNIX如下:

fout = open('fout', 'w') 
ferr = open('ferr', 'w')  
p = subprocess.Popen(argslist, stdout=fout, stderr=ferr) 
p.wait() 
fout.close() 
ferr.close()