2014-07-25 49 views
0

我正在編寫我的第一個python程序,我想運行一個shell命令並獲取輸出。我想用最乾淨/最pythonic的方式來做到這一點。這是我所掌握的。 注意:我還想在執行shell命令時發生異常時引發異常。從shell命令獲得輸出的最pythonic方法

def lsCommand(): 
    process = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    out , err = process.communicate() 
    returnc = process.returncode 
    if returnc != 0: 
     raise Exception(err) 
    else: 
     return out 

我發現什麼,就是當我刪除行出來,ERR = process.communicate(),並用time.sleep(4)(<替換它= ls命令不採取4秒完成),返回碼是無,這意味着它的子進程尚未完成。這怎麼可能?是否out,err = process.communicate()執行隱式wait()方法調用?

def lsCommand(): 
    process = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    time.sleep(4) 
    returnc = process.returncode 
    if returnc != 0: 
     print returnc 
     raise Exception(err) 
    else: 
     return out 

編輯:我使用python 2.7

我想做一個更長的命令須藤找到 「/媒體/ USB0」 型的F -name 「* .JPG」 | wc -l,但我不確定如何與Popen打電話,任何人都可以幫忙嗎?

回答

3

是的,communicate意味着wait;它會讀取過程'stdoutstderr,直到它們關閉。

在第二個例子中你PIPE的輸出爲ls;子進程ls被阻止寫入stdoutstderr,直到您從管道讀取 - 因此它將在4秒內完成,甚至4年,直到讀取這些描述符。但是,由於手動輪詢描述符容易出錯,因此類有communicate方法來避免陷阱。


對於一個非常Python化的方式輕鬆獲得命令的輸出,見Popen.check_output可因爲Python 3.1和2.7,儘管它不會隨着stderr失敗的內容引發異常。如果您需要將異常情況包含stderr的內容作爲消息,則您的第一個示例非常有用。


要調用的全部管道在Python中,你可以使用shell=True與全流水線的命令。

pipeline = subprocess.Popen(
    'sudo find "/media/usb0" -type f -name "*.JPG" | wc -l', 
    shell=True, 
    stdout=subprocess.PIPE, 
    stderr=subprocess.PIPE 
) 

但是,您也可以使用Popen s到make the pipeline

find = subprocess.Popen(
    ['sudo', 'find', '/media/usb0', '-type', 'f', '-name', '*.JPG'], 
    stdout=subprocess.PIPE 
) 
wc = subprocess.Popen(
    ['wc', '-l'], 
    stdin=find.stdout, 
    stdout=subprocess.PIPE, 
    stderr=subprocess.PIPE 
) 
find.stdout.close() 
wc.communicate() 
+0

我正在使用python 2.7,應該這麼說。抱歉。我將編輯我的問題 – Bosiwow

+0

我已經閱讀了關於check_output的信息,我試圖使用它,但它不起作用,將再次嘗試。謝謝。你有沒有碰巧知道如何使用它像一個更長的命令,像sudo find ...在我的第一篇文章中? – Bosiwow

+0

這是更pythonic,如果我不在乎err消息?:def lsCommand(): process = subprocess.check_output(['ls',' - l']) 返回進程 – Bosiwow

1

它不會調用time.sleep,它會等待命令完成執行,可能是4秒或更長。

當你打電話給process.communicate()它實際上會打電話給命令並設置process.returncode中的值。

如果你不會叫process.communicate()那麼默認的process.returncode值爲None,什麼其返回時,你time.sleep(4)替換process.communicate()

Popen.returncode

孩子返回代碼,以投票方式設置()和wait()(和間接溝通())。無值表示進程尚未終止。

負值-N表示孩子被信號N終止(僅限Unix)。

+0

謝謝你,非常有幫助。 – Bosiwow

+0

如果它解決了你的問題,選擇它作爲答案 – Nilesh

+0

它部分解決了這個問題,但我仍然想知道這是否是在python 2.7上寫的最乾淨的代碼來從shell命令中獲取輸出。還是有更清潔的方法? – Bosiwow

相關問題