【问题标题】:subprocess.check_output with grep command fails when grep finds no matches当 grep 找不到匹配项时,使用 grep 命令的 subprocess.check_output 失败
【发布时间】:2014-01-07 22:41:07
【问题描述】:

我正在尝试搜索文本文件并检索包含特定单词集的行。这是我正在使用的代码:

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 返回一个空字符串。

谢谢

【问题讨论】:

  • 使用pipes.quote(pocket_location) 允许路径包含shell 中的特殊字符,例如空格字符。

标签: python grep subprocess


【解决方案1】:

如果 grep 没有找到任何内容,我只想让 subprocess.check_output 返回一个空字符串。

好吧,太糟糕了。 grep 认为没有匹配是失败的,check_output 中的 check 的全部目的是检查失败,所以你明确要求以这种方式做事。以下是相关文档:

如果返回码不为零,则会引发 CalledProcessError。 CalledProcessError 对象将在 returncode 属性中具有返回码,在输出属性中具有任何输出。

对于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

【讨论】:

    【解决方案2】:
    tyrs = subprocess.check_output('grep "^A" %s | grep TYR || true' % pocket_location, shell = True).split('\n')
    

    【讨论】:

    • shell 命令以调用 true 结束,确保返回码始终为 0
    • 当然,如果 grep 因任何其他原因而失败,您就会被这种方法搞砸了。如果您对编程很认真,我建议您采用 abarnert 解决方案。
    猜你喜欢
    • 2021-12-24
    • 2015-01-29
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 2020-09-30
    • 1970-01-01
    相关资源
    最近更新 更多