2012-07-15 125 views
24

我想將子進程的stderr輸出重定向到stdout。常數STDOUT應該這樣做,不是嗎?將子進程stderr重定向到stdout

然而,

$ python >/dev/null -c 'import subprocess;\ 
         subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)' 

輸出的東西。爲什麼會出現這種情況,以及如何在stdout上獲取錯誤消息?

+0

順便說一句,它是固定在Python 3.5中。 – max 2017-05-26 18:43:10

回答

29

仔細閱讀source code給出了答案。

subprocess.STDOUT
特殊值,(...)表示標準誤差應進入同一手柄爲標準輸出:特別是,當它說,documentation是誤導。

由於標準輸出被設定爲「默認」(-1,技術上)時stderr=subprocess.STDOUT進行評價時,標準錯誤被設置爲「默認」的可能。不幸的是,這意味着stderr的輸出仍然是stderr。

爲了解決這個問題,通過在標準輸出文件,而不是subprocess.STDOUT

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"], 
         stderr=sys.stdout.buffer)' 

或者,與Python的傳統2.X版本的兼容性:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"], 
         stderr=sys.stdout.fileno())' 
+0

也可以將stderr保持原樣:'stderr = sys.stderr.fileno()'。很好的例子;我將在我的所有腳本中簡單地使用這種技術。我們有傳統的Python 2.x;因此我會確切地知道我告訴它在什麼地方沒有混淆。 – 2015-09-01 13:52:59

6

其實用subprocess.STDOUT完全是文檔中陳述了什麼:它將stderr重定向到標準輸出,以便例如

proc = subprocess.Popen(self.task["command"], shell=False, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
output = "" 
while (True): 
    # Read line from stdout, break if EOF reached, append line to output 
    line = proc.stdout.readline() 
    line = line.decode() 
    if (line == ""): break 
    output += line 

結果輸出包含stdout和stderr的輸出。

stderr=subprocess.STDOUT重定向所有stderr輸出直接 stdout調用進程,這是一個主要的區別。

+0

-1這種情況與'stdout'是'None'的問題無關。和'subprocess.STDOUT'不會重定向到「調用控制檯」(我認爲你的意思是當前進程給出的文件句柄1),如你自己的例子所示 - 如果你用'['ls','/404']',[不顯示錯誤信息](http://ideone.com/2JhcRT)。 – phihag 2013-05-13 07:27:34

+0

你有些不對。不過,我認爲這根本不相關,因爲這是爲了澄清您的文章是否有誤導性的文檔 - 事實並非如此。我會在你的帖子下面留言,但一年前我沒有被允許這麼做。 – Maxxim 2014-07-10 11:06:30

+0

'python -c'import subprocess,sys; subprocess.call([「ls」,「/ 404」],stderr = subprocess.STDOUT)'2>/dev/null'表示'ls'的stderr轉到stderr(文件描述符2),因爲你不會看到任何輸出(假設你的系統上沒有'/ 404')。 Python文檔真的在這個話題上引起了轟動,這對我們shell腳本編寫者來說尤其惱人,他們習慣於以各種方式操縱stdout/stderr,並且必須到這裏來找出如何做一些應該很簡單的事情非混淆。 – 2015-09-01 13:31:04

相關問題