2016-02-29 22 views
1

[編輯]
subprocess.Popen處理標準輸出的2個選項是stdout="a_file_name"stdout=subprocess.PIPE
stderr可以通過stderr=subprocess.STDOUT與其中任何一個組合。對於subprocess.stderr = STDOUT - stdout = PIPE比stdout =「a_file_name」更好嗎?

對於我目前正在做的(模糊測試),我的結果stdout="a_file_name"代碼稍短且更乾淨。

但是,從我所看到的,似乎stdout=PIPE往往是其他人的首選,但我不確定所有原因爲什麼。

如果Popen([cmd, arg], ...)使用的cmd是錯誤輸出寫入stderr外部可執行文件,是stdout=PIPE某種程度上比stdout="a_file_name"更好?

各有什麼優點和缺點?

  • 在我的特定情況下(見下面的代碼片段),1個優勢,我可以看到使用stdout=PIPE而不是stdout="a_file_name"在於,前者可以讓我輕鬆地跳過寫一個空文件。
  • 在發生cmd崩潰事件時,2中的1會以某種方式更容易得到所有錯誤輸出?

雖然我有我的特定背景,但我也很想知道更一般情況下的答案。

爲了更好地解釋我的上下文,這裏是我的2替代代碼​​段:

import subprocess 
import sys 

assert sys.version_info >= (3, 3) 
    # timeout added for subprocess's wait() and communicate() in Python 3.3. 

with open('sub_proc1.outerr', 'w') as f_outerr1: 
    sub_proc1 = subprocess.Popen([cmd, args], stdout=f_outerr1, 
           stderr=subprocess.STDOUT, 
           universal_newlines=True) 
    try: 
     return_code = sub_proc1.wait(timeout=10) 
     print('*** %s CRASHED with return code: %d.' % (cmd, return_code)) 
    except subprocess.TimeoutExpired: 
     print('*** %s succeeded.' % cmd) 
     sub_proc1.kill() 

與:

... 
with open('sub_proc2.outerr', 'w') as f_outerr2: 
    sub_proc2 = subprocess.Popen([cmd, args], stdout=subprocess.PIPE, 
           stderr=subprocess.STDOUT, 
           universal_newlines=True) 
    try: 
     (sub_proc2_out, sub_proc2_err) = sub_proc2.communicate(timeout=10) 
     print('*** %s CRASHED with return code: %d.' % 
       (cmd, sub_proc2.poll())) 
     assert sub_proc2_err is None 
      # Since stderr was redirected to STDOUT, this should be None. 
     f_outerr2.write(str(sub_proc2_out or "")) 
      # Treat 'None' as an empty string). 
    except subprocess.TimeoutExpired: 
     print('*** %s succeeded.' % cmd) 
     sub_proc2.kill() 

原貼:

標題:子:優點和缺點stderr = STDOUT與stderr = PIPE?

從 'subprocess.Popen' 處理錯誤輸出的2個主要替代似乎是 '標準錯誤= STDOUT'(與 '標準輸出= 「SOME_FILE」')和 '標準錯誤= PIPE'。

對於我想要做的(模糊測試),我的結果'stderr = STDOUT' 代碼有點短而且更乾淨。

但是,從我所讀到的看來,'stderr = PIPE'是 首選,但我不確定所有原因。

如果「加利福尼亞」所使用的是其誤差輸出 寫入「stderr的」外部的可執行文件,什麼是使用「標準錯誤= STDOUT」 與「標準錯誤= PIPE」的利弊?

...

+0

如果您在測試程序中沒有對輸出進行任何操作(寫入文件除外),我認爲這兩個代碼之間沒有太大區別。如果您想查看輸出的實際細節(例如將其包含在您的'print'調用中,或者檢查它是否寫出特定的字符串),那麼使用'PIPE'將是必要的。第一個代碼的一個可能的優點是,如果正在運行的程序交替寫入它們,它將交錯stdout和stderr流。另一方面,你不能分辨出兩個輸出! – Blckknght

+0

謝謝你的有用評論,Blckknght。 如果我想檢查輸出的實際細節,我可以看到PIPE會是更好的選擇。 在我的特殊情況下,使stdout和stderr流交錯很好。 – Russell

+0

您的評論讓我意識到以前沒有意識到的東西。 這種交錯可以與任一方法: 標準輸出= 「a_file_name」,標準錯誤= subprocess.STDOUT 或 標準輸出= subprocess.PIPE,標準錯誤= subprocess.STDOUT 類似地,具有所述stdout和sterrr流非交錯是也可以用以下任一方法: stdout =「file_name_1」,stderr =「file_name_2」 或 stdout = subprocess.PIPE,stderr = subprocess.PIPE – Russell

回答

1

寫入特定文件意味着如果您的程序每次運行多次都會發生衝突,因爲兩個進程都希望寫入同一個文件。 (搜索臨時文件創建和安全漏洞的問題)

使用管道意味着不存在文件名唯一性問題。

你關心輸出嗎?如果不是,則使用subprocess.DEVNULL,它會爲您丟棄輸出。

+0

感謝您的回答dsh。 我可以看到寫入特定文件可能會導致名稱衝突。 不過,我的腳本根據當前日期/時間將其所有輸出寫入子文件夾,所以這不應該是一個問題: 'out_fdr = time.strftime(os.path.join(' %Y','%m','%d','%H.%%M.%S'))' 我確實關心輸出。 到目前爲止,我從我的.outerr文件中獲得了一些有用的信息,例如: 內存不足 或 虛假內存分配大小 – Russell

+0

如果它在同一秒內運行兩次,則會在目錄上產生名稱衝突:)。如果你想保存輸出供將來使用,那麼文件更合適。如果你想在你的程序中處理輸出,那麼管道更自然。 – dsh

+0

這是一個大加。 我的PDF模糊測試通常發現碰撞<1%的時間,而PIPE將讓我只寫一個stderr輸出文件,如果: 1.有stderr輸出要寫入。 AND 2.發生崩潰。 [原本我用stderr =「a_file_name」,然後刪除文件,如果它是空的或沒有崩潰。] 謝謝。 – Russell