2015-02-23 65 views
4

命令框架,以確定是否Xcode是在Mac上運行:cmd = "ps -ax | grep -v grep | grep Xcode"蟒蛇check_output失敗,退出狀態1,但POPEN適用於相同的命令

如果Xcode中沒有運行,那麼上面的命令與subprocess模塊的Popen方法效果很好,但用check_output方法提出CalledProcessError。我嘗試通過以下代碼檢查stderr,但未能獲得適當的信息以瞭解原因。

from subprocess import check_output, STDOUT, CalledProcessError 

psCmd = "ps -ax | grep -v grep | grep Xcode" 
o = None 
try: 
    o = check_output(psCmd, stderr=STDOUT, shell=True) 
except CalledProcessError as ex: 
    print 'Error:', ex, o 

異常信息如下:

Error: Command 'ps -ax | grep -v grep | grep Xcode' returned non-zero exit status 1 None

問:爲什麼POPEN上面的命令工作,但失敗check_output?

注意:如果Xcode正在運行,Command與兩種方法都能很好地協作。

+0

無論如何,你在Python本身執行'grep'處理要好得多。 – tripleee 2015-02-23 14:58:18

+0

即使我在python中處理輸出,我也必須使用'subprocess'模塊。所以我認爲這是在'bash'結束所有工作的好方法。 – Deepak 2015-02-23 15:18:22

+0

相關:[在Python中通過名稱殺死進程](http://stackoverflow.com/q/2940858/4279) – jfs 2015-02-24 07:12:50

回答

16

check_output()按預期工作。下面是它在Popen()方面簡化實現:

def check_output(cmd): 
    process = Popen(cmd, stdout=PIPE) 
    output = process.communicate()[0] 
    if process.returncode != 0: 
     raise CalledProcessError(process.returncode, cmd, output=output) 
    return output 

grep回報1如果還沒有發現任何東西,即你應該期望的異常,如果Xcode中沒有運行。

注:爲實施顯示,你甚至可以在發生異常得到的輸出:

#!/usr/bin/env python 
from subprocess import check_output, STDOUT, CalledProcessError 

cmd = "ps -ax | grep -v grep | grep Xcode" 
try: 
    o = check_output(cmd, stderr=STDOUT, shell=True) 
    returncode = 0 
except CalledProcessError as ex: 
    o = ex.output 
    returncode = ex.returncode 
    if returncode != 1: # some other error happened 
     raise 

你很可能pgrep -a Xcode命令代替(注:始於p)或使用psutil模塊的便攜式代碼:

#!/usr/bin/env python 
import psutil # $ pip install psutil 

print([p.as_dict() for p in psutil.process_iter() if 'Xcode' in p.name()]) 
+0

我現在明白了,爲什麼check_output表現爲行爲。檢查返回代碼是否很酷。我會用你的想法與errno。一些**懷疑**:_1._爲什麼我們必須在值爲0的'try'塊中初始化'returncode'?_2_。我們不能比較'ex.returncode'直接在'if'條件下的值爲1嗎?它是否有助於某些目的,我還沒有明白。 – Deepak 2015-02-25 07:58:58

+2

're turncode'設置在try /裏,除非爲了讓你知道check_output()沒有引發異常,它總是爲零2.兩個分支(有和沒有例外)設置兩個變量:你可以使用代碼後的'o'和'returncode',而不管Xcode是否在運行。 – jfs 2015-02-25 08:02:07

2

從Python文檔:「如果返回代碼是非零它引發一個CalledProcessError。」。這就是Xcode不運行時發生的事情;由於grep找不到您要查找的字符串Xcode,因此最終的grep Xcode以非零狀態退出。因此,check_output()將引發異常。我發現這個the Python subprocess documentation

+0

我不這麼認爲。如果我在沒有啓動Xcode的終端中運行此命令並檢查errno變量,它仍然保持值0.要檢查errno,我使用了echo「$?」。 – Deepak 2015-02-23 14:43:24

+1

嗯...當我嘗試'ps -aef | grep -v grep | grep Xcode; echo $?',我得到輸出:'1' – 2015-02-23 14:53:33

+0

@DeepakrajHR你的意思是即使Xcode沒有啓動你的grep命令找到它了嗎?您顯示錯誤消息'錯誤:命令'ps -ax | grep -v grep | grep Xcode返回的非零退出狀態1 None'是你的python腳本的輸出,因爲你已經在你的代碼中處理了異常 – 2015-02-23 14:55:08

1

如果你的grep命令grep Xcode返回任何結果,那麼該命令的returncode將是非零的,這就是爲什麼check_output呼籲CalledProcessError,這是你在print命令的輸出所看到的

要獲得你的命令的輸出是它下面的代碼錯誤或成功使用: - 如果它的返回碼0否則它會調用異常

#!/usr/bin/python 
from subprocess import check_output, STDOUT, CalledProcessError 

psCmd = "ps -aef | grep -v grep | grep Xcode" 
o = None 
o = check_output(psCmd+";exit 0", stderr=STDOUT, shell=True) 

check_output只會顯示你的命令的輸出。

+0

請參閱我對Karel Kubat的回答的評論 – Deepak 2015-02-23 14:46:01

+0

這是一個不錯的想法,如[link](https://docs.python.org/2/library/subprocess.html#subprocess.check_output)所示。但是,爲什麼我從Python腳本得到的錯誤代碼是1,終端是0。無論如何,現在我正在使用Popen來解決問題。但是問題仍然存在:-( – Deepak 2015-02-23 15:09:09

+0

我得到了我的答案,現在我正在使用這種方式,但現在我想知道,如果命令因其他未知原因而失敗會怎麼樣,我認爲這也會因爲退出而繞過0'。是否有辦法來捕捉這些例外 – Deepak 2015-02-23 15:24:56

0

check_output的目的是確保您運行的命令成功完成。如果grep Xcode沒有成功,假設失敗。

無論如何,在Python中進行搜索時,你想要的會更簡單。

output = check_output(['ps', '-ax'], shell=False) 
if 'Xcode' in output: 
    print('Xcode appears to be running') 

這個擁有它實際上失敗,如果ps由於某種原因失敗外殼版本的附加(很輕微的)好處。當它不在管道末端時,shell將簡單地忽略ps的退出代碼。

相關問題