等同于Python中的Bash反引号[重复]


84

相当于在Ruby和Perl中使用Python的反引号是什么?也就是说,在Ruby中,我可以这样做:

foo = `cat /tmp/baz`

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


Answers:


100
output = os.popen('cat /tmp/baz').read()

4
@mckenzm问题是关于捕获外部进程的输出。捕获Python函数的输出将是一个完全不同的问题。
约翰·库格曼

1
简明扼要,`...`简直与Ruby相当(捕获stdout,将stderr传递通过)-一个例外:Ruby允许在$?事后确定进程的退出代码;在Python中,据我所知,您必须为此使用subprocess模块的功能。
mklement0 '19

82

最灵活的方法是使用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,如果您需要扩展诸如的文件名之类的功能,则可以通过外壳执行该程序*,但这带有局限性


2
是的,这是唯一明智的方法,您可以将其包装在函数中,以便可以调用诸如execute(“ command”)之类的东西
Vinko Vrsalovic

这实际上对我不起作用,因为在这种情况下,baz是目录,并且我正在尝试获取该目录中所有文件的内容。(做cat / tmp / baz / *可以用滴答作答,但不能通过此处描述的方法进行)
克里斯·邦奇

6
回复:“ *”不起作用;请改用subprocess.Popen([“ cat”,“ / tmp / baz”],stdout = subprocess.PIPE,shell = True)。由于glob(星号)扩展由shell处理,因此在这种情况下,子处理模块必须使用shell扩展(由/ bin / sh提供)。
Pasi Savolainen 09年

1
来自docs.python.org/2/library/subprocess.html#popen-constructor:“(带有shell = True)如果args是序列,则第一项指定命令字符串,任何其他项将被视为其他参数。外壳本身。” 因此,如果要使用shell = True,则第一个arg可能应该是字符串“ cat / tmp / baz”。另外,如果您要使用序列作为第一个参数,则应使用shell = False
onlynone 2013年

1
@gerrit:不建议使用。如果您不需要支持早期版本或不需要的灵活性,则文档会建议 subprocess.run()(我不知道是否值得这样做)Popen()
jfs

27

某事是对的。您也可以使用os.popen(),但通常最好使用(Python 2.4+)子进程。

但是,与某些鼓励使用该语言的语言不同,生成一个子过程通常可以认为是不好的形式,在子过程中您可以在该语言中完成相同的工作。它速度较慢,可靠性较低且与平台有关。您的示例将更好,因为:

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

eta:

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

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

如果要文件列表:

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))

1
尽管这不是问题的答案,但这是教育用户的最佳答案。
noamtm

1
问题标题是“什么是反引号”。我以为“ cat”只是一个示例命令。这个答案对一般情况没有帮助。
杰森

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

3
这是现在最直接的方法。在给出其他“ popen”答案之后,于2010年7月发布的Python 2.7中添加了“ subprocess.check_output”。
罗伯特·弗莱明

10

从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对象。


从python 3.7开始,您可以使用text=True参数取回str而不是字节。
bwv549


3
import os
foo = os.popen('cat /tmp/baz', 'r').read()

3
这等效于Ruby的反引号,但是如果您的问题是列出目录的内容,那么这不是最好的方法。
awatts

2

我正在使用

(6:0] $ python-版本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。查看子流程的文档字符串后,我替换了

[“ prog”,“ arg”]

“程序arg”

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

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


我前一段时间不使用python,因为我对做等效于perl`cmd ...`的困难感到恼火。我很高兴发现Python使这变得合理。


1

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


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`

4
您也可能不应该这样做*
ThorSummoner

-1

repr()

backtick(`)运算符辗转Python 3。它与单引号一样令人困惑,并且在某些键盘上很难键入。而不是backtick使用等效的内置函数repr()


那不等同于bash反引号。
Gerrit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.