2014-01-07 46 views
4

我正在嘗試搜索文本文件並檢索包含特定字詞集的行。這是我正在使用的代碼:當grep找不到匹配項時,使用grep命令執行subprocess.check_output失敗

tyrs = subprocess.check_output('grep "^A" %s | grep TYR' % pocket_location, shell = True).split('\n') 

當文件至少包含grep標識的一行時,此功能正常。但是,當grep的不識別任何行,grep的返回退出狀態1,我得到以下錯誤:

Traceback (most recent call last): 
    File "../../Python_scripts/cbs_wrapper2.py", line 324, in <module> 
    tyrs = subprocess.check_output('grep "^ATOM" %s | grep TYR' % pocket_location, shell = True).split('\n') 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 544, in check_output 
    raise CalledProcessError(retcode, cmd, output=output) 
subprocess.CalledProcessError: Command 'grep "^ATOM" cbsPrediction_files/1u9c_clean/1u9c_clean_fpocket_out/pockets/pocket0_atm.pdb | grep TYR' returned non-zero exit status 1 

我怎樣才能避免這個問題?如果grep找不到任何東西,我只想subprocess.check_output返回一個空字符串。

感謝

+0

使用'pipes.quote(pocket_location)'允許與處於一個特殊的外殼,如空格字符的路徑。 – jfs

回答

4
tyrs = subprocess.check_output('grep "^A" %s | grep TYR || true' % pocket_location, shell = True).split('\n') 
+0

謝謝!你介意解釋爲什麼這會起作用嗎? – Korem

+3

shell命令以調用true來結束,以確保返回代碼始終爲0 – yaccz

+0

當然,如果grep由於其他原因而失敗,那麼您將使用此方法。如果你認真對待編程,我建議採取一些解決方案。 – yaccz

8

I just want subprocess.check_output to return an empty string if grep doesn't find anything.

好了,太糟糕了。 grep認爲沒有匹配項是失敗的,並且中的check的整個點是檢查失敗,所以您明確要求這樣做。以下是相關的文檔:

If the return code was non-zero it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute and any output in the output attribute.

併爲grep

The following exit values shall be returned: 
    0 One or more lines were selected. 
    1 No lines were selected. 
    >1 An error occurred. 

所以,如果你想治療「無行」的成功,但實際作爲錯誤,你必須處理1值與其他非零值不同。並且check_output不知道你想這麼做。

所以,要麼你必須處理CalledProcessError,要麼你必須自己檢查。換句話說,無論是這樣的:

try: 
    tyrs = subprocess.check_output('grep "^A" %s | grep TYR' % pocket_location, shell = True).split('\n') 
except subprocess.CalledProcessError as e: 
    if e.returncode > 1: 
     raise 
    tyrs = [] 

...或這個:

p = subprocess.Popen('grep "^A" %s | grep TYR' % pocket_location, shell=True, 
        stdout=subprocess.PIPE) 
output, _ = p.communicate() 
if p.returncode == 1: # no matches found 
    tyrs = [] 
elif p.returncode == 0: # matches found 
    tyrs = output.split('\n') 
else: 
    # error, do something with it