2012-12-17 47 views
2

我正在編譯一個命令在python unix系統上執行,包含多個管道步驟。例如: -錯誤檢查管道命令在python中爲unix

grep foo myfile | cmd1 | cmd2 > output 

這些對應於在具有foo在他們myfile條目的一系列的變換。我有時將其構造爲os.system執行的命令,在其他情況下使用subprocess模塊執行。

如何從Python中對管道的每個部分執行錯誤檢查?例如,在99%的情況下,myfile中有foo條目,其餘管道工程。但是,如果由於某種原因myfile存在但不包含foo條目,則管道的其餘部分會因爲管道空文件而中斷,而其餘命令需要非空輸入才能工作。這使得它很難調試,因爲你看到的是一個破裂的管道輸出,不知道這中間步驟失敗。

有沒有一種方法來構建Python中的錯誤檢查中間步驟的管道?例如。檢查管道的grep部分是否確實包含某些輸出,grep的輸入上的cmd1輸出是否還包含某些輸出,依此類推?謝謝。

+0

做到這一點,最簡單的方法是做事情本地在Python中。調用從OS來回和Python只是引入了額外的變量和通常最好在第一時間避免了複雜性。 –

+0

所以,你會怎麼做它在Python,如果它需要調用外部命令?我知道的唯一方法是''subprocess''。我無法改寫我在Python中調用的所有命令 – user248237dfsf

+2

在bash中,您有PIPESTATUS變量 - 如果可以的話使用。 否則就像在sr2222建議的python中那樣做 - 設置管道,用重定向輸入輸出啓動程序,檢查它們的退出狀態,那有什麼問題?你提到的模塊甚至以stdin/stdout/stderr作爲參數! – loreb

回答

0

這是我的方法,在Python 2.6 Linux上測試過。

a.Define的方法

def run_command(command): 
    p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    out, err = p.communicate() 
    return (p.returncode, out, err) 

b。使用它通過以下方式

def test_run_command_pipestatus(self): 
    # the exit $PIPESTATUS is the return code of "exit 2". The default return code is the return code of last command in the pipe 
    return_code, out, err = run_command("exit 2 | tail -n 1; exit $PIPESTATUS") 
    print "return_code = %d" %return_code 
    print out 
    print err 
    self.assertEqual(2, return_code) 
0

基本上一樣岷江石的回答,其中有大部分是你所需要的關鍵信息,但沒有額外的功能,並修復問題。 (並在python 2.7.12和3.5.2中測試)

$ PIPESTATUS在sh中不存在,所以如果您的發行版沒有/bin/sh,就像bash(比如Ubuntu其使用dash)。它是一個數組,所以我更喜歡像一個一樣使用它。

,我建議wait()代替communicate(),這樣你就可以(爲你處理任何前要在內存讀入一個小緩衝區,而不是全負荷輸出的使用),而不是過濾啜食的。

因此,所有你需要做的是:

  • 應該使用一個字符串,而不是爲ARGS
  • 使用外殼列表=真
  • 使用可執行= 「/斌/慶典」

代碼:

p = subprocess.Popen("false | true; exit ${PIPESTATUS[0]}", shell=True, executable='/bin/bash', stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

# at this point you do your filtering, eg. using p.stdout.readinto(buf) 

p.wait() 
if p.returncode != 0: 
    # handle it here