在Python中使用subprocess进行grep/zgrep

1 投票
2 回答
4910 浏览
提问于 2025-04-18 07:53

我有一堆文件,它们的格式是*.tsv.gz的压缩文件,还有一些是没有压缩的*.tsv文件,放在一个文件夹里。

我想从这些文件中查找一个特定的字符串,并把找到的结果每个都打印在新的一行上。

我写了一个函数,这个函数可以接收一个输入目录,里面存放着tsv和*.tsv.gz文件,还有要搜索的字符串。

import sys, os, traceback,subprocess,gzip,glob
def filter_from_tsvs(input_dir,string):

    tsvs = glob.glob(os.path.join(input_dir,'*.tsv*'))
    open_cmd=open
    for tsvfile in tsvs:
        print os.path.splitext
        extension = os.path.splitext(tsvfile)[1]
        if extension == ".gz":
          open_cmd = gzip.open
    print open_cmd
    try:
        print subprocess.check_output('grep string tsvfile', shell=True)

    except Exception as e:
        print "%s" %e
        print "%s" %traceback.format_exc()
return

我也试过使用:

         try:
             fname = open_cmd(tsvfile,"r")
             print "opened"
             print subprocess.check_output('grep string fname', shell=True)

但是我遇到了这个错误:

gzip: tsvfile.gz: No such file or directory
Command 'zgrep pbuf tsvfile' returned non-zero exit status 2
Traceback (most recent call last):
  File "ex.py", line 23, in filter_from_maintsvs
    print subprocess.check_output('zgrep pbuf tsvfile', shell=True)
  File "/datateam/tools/opt/lib/python2.7/subprocess.py", line 544, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command 'zgrep pbuf tsvfile' returned non-zero exit status 2`

我该如何在Python中使用grep或zgrep呢?

2 个回答

2

关于你的代码,有几点建议:

现在你把要查找的字符串和文件名写死了,分别是'string'和'tsvfile'。可以试试这样:

subprocess.check_output(['grep', string, tsvfile])

接下来,如果你使用的是 zgrep,那么就不需要用 gzip.open 来打开文件。你可以直接对一个 tsv.gz 文件使用 zgrep,它会自动帮你打开文件,你不用额外操作。所以可以试试这样调用:

subprocess.check_output(['zgrep', string, tsvfile]) 

需要注意的是,zgrep 也可以处理未压缩的 tsv 文件,所以你不需要在 grep 和 zgrep 之间来回切换。

3

我在看了一个博客后找到了以下解决方案,并且对我有效 :)

import subprocess
import signal

output = subprocess.check_output('grep string tsvfile', shell=True, preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))

print output  

提示:

  • 如果没有找到这个字符串,grep 会返回一个退出代码 1,这时 check_output 会抛出一个异常。
  • check_output 从 Python 2.7 开始就可以用了。如果你需要其他方法,可以查看这里

撰写回答