88

Python 中的 Ruby 和 Perl 中的反引号等价物是什么?也就是说,在 Ruby 中我可以这样做:

foo = `cat /tmp/baz`

Python 中的等效语句是什么样的?我已经尝试过os.system("cat /tmp/baz"),但这会将结果标准化并返回给我该操作的错误代码。

4

11 回答 11

107
output = os.popen('cat /tmp/baz').read()
于 2009-09-11T13:53:48.113 回答
85

最灵活的方式是使用subprocess模块:

import subprocess

out = subprocess.run(["cat", "/tmp/baz"], capture_output=True)
print("program output:", out)

capture_output在 Python 3.7 中引入,对于旧版本,check_output()可以使用特殊功能:

out = subprocess.check_output(["cat", "/tmp/baz"])

如果您需要细粒度控制,您还可以手动构造子流程对象:

proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE)
(out, err) = proc.communicate()

所有这些函数都支持关键字参数来自定义子流程的执行方式。例如shell=True,如果您需要文件名扩展之类的东西,您可以通过 shell 执行程序*,但这有限制

于 2009-09-11T13:52:17.243 回答
28

某事是对的。您也可以使用 os.popen(),但在可用的情况下(Python 2.4+)子进程通常更可取。

但是,与一些鼓励它的语言不同,通常认为生成一个子进程是不好的形式,您可以在该子进程中在该语言中执行相同的工作。它速度较慢,可靠性较低且依赖于平台。你的例子会更好:

foo= open('/tmp/baz').read()

埃塔:

baz 是一个目录,我正在尝试获取该目录中所有文件的内容

? 目录上的 cat 给我一个错误。

如果你想要一个文件列表:

import os
foo= os.listdir('/tmp/baz')

如果您想要目录中所有文件的内容,例如:

contents= []
for leaf in os.listdir('/tmp/baz'):
    path= os.path.join('/tmp/baz', leaf)
    if os.path.isfile(path):
        contents.append(open(path, 'rb').read())
foo= ''.join(contents)

或者,如果您可以确定其中没有目录,则可以将其放入单行中:

path= '/tmp/baz'
foo= ''.join(open(os.path.join(path, child), 'rb').read() for child in os.listdir(path))
于 2009-09-11T14:00:11.497 回答
16
foo = subprocess.check_output(["cat", "/tmp/baz"])
于 2011-09-19T09:58:22.763 回答
12

从 Python 3.5 开始,推荐的方法是使用subprocess.run. 从 Python 3.7 开始,要获得与您描述的相同的行为,您将使用:

cpe = subprocess.run("ls", shell=True, capture_output=True)

这将返回一个subprocess.CompletedProcess对象。到 stdout 的输出将是 in cpe.stdout,到 stderr 的输出将是 in cpe.stderr,它们都是bytes对象。str您可以通过使用cpe.stdout.decode()或通过传递text=True来解码输出以获取对象subprocess.run

cpe = subprocess.run("ls", shell=True, capture_output=True, text=True)

在后一种情况下,cpe.stdoutcpe.stderr都是str对象。

于 2016-03-22T16:39:33.270 回答
6

最简单的方法是使用命令包。

import commands

commands.getoutput("whoami")

输出:

'bganesan'

于 2014-07-28T17:48:01.213 回答
3
import os
foo = os.popen('cat /tmp/baz', 'r').read()
于 2009-09-11T13:55:24.663 回答
2

我在用着

(6:0)$ python --version Python 2.7.1

上述示例之一是:

import subprocess
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out

对我来说,这无法访问目录 /tmp。在查看了子进程的文档字符串后,我替换了

[“前卫”,“arg”]

“程序 arg”

并获得了所需的 shell 扩展行为(a la Perl 的 `prog arg`)

打印 subprocess.Popen("ls -ld /tmp/v*", stdout=subprocess.PIPE, shell=True).communicate()[0]


不久前我放弃了使用 python,因为我对执行 perl `cmd ...` 的等效操作感到恼火。我很高兴发现 Python 使这变得合理。

于 2011-03-11T23:13:34.750 回答
1

这在 python3 中不起作用,但在 python2 中,您可以str使用自定义__repr__方法进行扩展,该方法调用您的 shell 命令并返回它,如下所示:

#!/usr/bin/env python

import os

class Command(str):
    """Call system commands"""

    def __repr__(cmd):
        return os.popen(cmd).read()

你可以像这样使用

#!/usr/bin/env python
from command import Command

who_i_am = `Command('whoami')`

# Or predeclare your shell command strings
whoami = Command('whoami')
who_i_am = `whoami`
于 2015-04-19T19:48:17.440 回答
1

如果使用 subprocess.Popen,请记住指定 bufsize。默认值为 0,表示“无缓冲”,而不是“选择合理的默认值”。

于 2010-04-13T02:55:41.623 回答
-1

repr()

( backtick`) 运算符已在中删除Python 3。它与单引号令人困惑地相似,并且难以在某些键盘上键入。代替backtick,使用等效的内置函数repr()

于 2019-04-09T19:51:45.080 回答