在Python中执行shell反引号操作?

4
我正在将 Bash 脚本翻译成 Python,出于某些原因。
Python 更强大,然而,编写像这样简单的 Bash 代码却要困难得多:
MYVAR = `grep -c myfile`

使用Python,我首先需要定义一个反引号函数,可以是:
def backquote(cmd,noErrorCode=(0,),output=PIPE,errout=PIPE):
    p=Popen(cmd, stdout=output, stderr=errout)
    comm=p.communicate()
    if p.returncode not in noErrorCode:
        raise OSError, comm[1]
    if comm[0]:
        return comm[0].rstrip().split('\n')

那很无聊!
有没有 Python 的变体(比如 IPython),可以轻松地生成进程并获得输出?
4个回答

9
在Python 2.7或以上版本中,有一个名为subprocess.check_output()的函数,基本上可以实现你需要的功能。

1
++, 不知道有这个函数 - Eli Bendersky

4

os.subprocess文档介绍了如何替换反引号:

output=`mycmd myarg`
==>
output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]

这基本上就是OP正在做的事情,但还要检查返回值并返回一系列行... - Mark Longair
来自RHEL6用户的投票。 - Maciej Wawrzyńczuk

2

定义了这个backquote函数之后,你可以在程序中以及交互式shell(IPython等)中反复调用它。

在Python中没有直接使用这样的“反引号”的方式,而且我认为这是有充分理由的。Python以其易读性而著称,将这样的结构纳入语言中会鼓励编写难以阅读的“脚本式”代码。话虽如此,“backquote”可能并不是一个最具描述性的函数名称,因为它返回子进程的输出。


+1 我也是这么想的。@Eric:你定义函数的方式有什么问题吗?可以称其为“反引号”或其他你喜欢的名称,并在需要时导入它。 - ypercubeᵀᴹ

0
如Andrea所说,您应该使用subprocess.Popen - 无需扩展输入 - 您可以在单独的文件中执行此操作,例如“helper.py”,然后在脚本中导入它:
from subprocess import Popen, PIPE

def r(cmd_line):
    return Popen(cmd_line.split(), stdout=PIPE).communicate()[0]

而在你的其他文件中,你可以这样做

from helper import r

print r("ls -l")
print r("pwd")
r("tar czvf new_tarball.tar.gz %s" % path_to_archive)

请注意,如果您必须在参数中传递空格(例如"My Documents"参数)给shell命令,则此简化方法将无法正常工作。在这种情况下,要么显式地使用Popen,要么增强辅助函数以便能够处理它。简单地用“\”转义空格将被我在那里使用的split忽略。

使用 shlex.split 而不是 string.split 可以避免引用问题。 - Matthew Hannigan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接