Python 子进程 Grep
我正在尝试在一个Python脚本中使用grep命令,使用的是subprocess模块。
这是我目前的代码:
userid = 'foo12'
p = subprocess.Popen(['grep', "%s *.log"%userid], stdout=subprocess.PIPE)
但是它什么都没有返回。我不太确定我哪里做错了,所以能不能有人解释一下?我现在使用的方法是加上shell=true,这样可以输出正确的结果,但帮助页面上说这样不安全。我需要帮助,让我的脚本在安全的情况下正常工作。
3 个回答
6
我猜你是想在所有以 '.log' 结尾的文件中查找 'foo12',如果你想用 subprocess
来实现这个功能,你需要把你的代码改成下面这样:
userid = 'foo12'
p = subprocess.Popen('grep %s *.log' % userid, stdout=subprocess.PIPE, shell=True)
shell=True
是必须的,这样才能让通配符生效。当你设置了这个选项后,你需要提供一个字符串命令,而不是一个列表。
另外,确保在提供参数列表时,每个参数都是列表中的一个单独项,你最开始的代码其实相当于下面这样:
grep 'foo12 *.log'
11
这里有两段经过测试的代码可以参考:
>>> print subprocess.check_output(['grep', 'python', 'api_talk.txt'])
Discuss python API patterns
Limitations of python
Introspection in python
>>> print subprocess.check_output('grep python *.txt', shell=True)
如果你希望命令行自动处理通配符,可以使用后者。当shell设置为True时,记得把整个命令放在一个字符串里,而不是分成多个部分。
13
我觉得你遇到了两个问题:
首先,这段代码:
p = subprocess.Popen(['grep', "%s *.log"%userid]...
如果不加
shell=True
,它不会按预期工作,因为你传给os.execvp
的参数列表是直接传递的,而这个函数要求每个参数都是一个单独的字符串。你把两个不同的参数合并成了一个字符串(换句话说,grep把"foo12 *.log
"当成了要搜索的模式,而不是模式加文件列表)。你可以通过这样做来解决这个问题:
p = subprocess.Popen(['grep', userid, '*.log']...)
第二个问题是,同样如果不加
shell=True
,execvp
并不知道你说的*.log
是什么意思,它会直接把这个传给grep,而不会经过shell的通配符扩展机制。如果你不想使用shell=True
,你可以尝试这样做:import glob args = ['grep', userid] args.extend(glob.glob('*.log') p = subprocess.Popen(args, ...)