在Python中使用subprocess进行grep/zgrep
我有一堆文件,它们的格式是*.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 开始就可以用了。如果你需要其他方法,可以查看这里。