Python中Bash反引号的等价物[重复]

Posted

技术标签:

【中文标题】Python中Bash反引号的等价物[重复]【英文标题】:Equivalent of Bash Backticks in Python [duplicate] 【发布时间】:2010-11-27 12:19:45 【问题描述】:

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

foo = `cat /tmp/baz`

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

【问题讨论】:

***.com/questions/2924310/… 【参考方案1】:
output = os.popen('cat /tmp/baz').read()

【讨论】:

@mckenzm 问题是关于捕获外部进程的输出。捕获 Python 函数的输出将是一个完全不同的问题。 非常简洁,实际上相当于 Ruby 的`...`(捕获标准输出,传递标准错误)——除了一个例外:Ruby 允许在事后通过$? 确定进程的退出代码;在 Python 中,据我所知,您必须为此使用 subprocess 模块的函数。【参考方案2】:

最灵活的方式是使用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()

所有这些函数都支持keyword parameters 来自定义子流程的执行方式。例如,您可以使用 shell=True 通过 shell 执行程序,如果您需要 * 的文件名扩展之类的东西,但 limitations 附带。

【讨论】:

是的,这是唯一理智的方法,你可以将它包装在一个函数中,这样你就可以调用类似 execute("command") 这实际上对我不起作用,因为在这种情况下, baz 是一个目录,我正在尝试获取该目录中所有文件的内容。 (做 cat /tmp/baz/* 工作在滴答声中,但不是通过这里描述的方法) 回复:“*”不起作用;使用 subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True) 代替。由于glob(星形)扩展由shell处理,因此子处理模块在这种情况下必须使用shell扩展(由/bin/sh提供)。 来自docs.python.org/2/library/subprocess.html#popen-constructor : "(with shell=True) 如果 args 是一个序列,第一项指定命令字符串,任何附加项将被视为 shell 本身的附加参数。"因此,如果您要使用 shell=True,那么第一个 arg 可能应该是字符串“cat /tmp/baz”。或者,如果您想使用序列作为第一个参数,那么您应该使用 shell=False @gerrit:它没有被弃用。如果您不需要支持早期版本或不需要Popen() 提供的灵活性,文档推荐 subprocess.run()(我不知道是否值得)。 【参考方案3】:

sth is right。您也可以使用 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))

【讨论】:

虽然这不是问题的答案,但它是教育用户的最佳答案。 问题标题是“什么是反引号的等价物”。我假设“cat”只是一个示例命令。这个答案对一般情况没有帮助。【参考方案4】:
foo = subprocess.check_output(["cat", "/tmp/baz"])

【讨论】:

这是目前最直接的方式。在给出其他“popen”答案之后,在 2010 年 7 月发布的 Python 2.7 中添加了“subprocess.check_output”。【参考方案5】:

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

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

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

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

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

【讨论】:

从 python 3.7 开始,您可以使用 text=True 参数来获取 str 而不是字节。【参考方案6】:

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

import commands

commands.getoutput("whoami")

输出:

'bganesan'

【讨论】:

非常简单,但该模块现已弃用。【参考方案7】:
import os
foo = os.popen('cat /tmp/baz', 'r').read()

【讨论】:

这相当于 Ruby 的反引号,但如果您的问题是列出目录的内容,那么这不是最好的方法。【参考方案8】:

我正在使用

(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”]

“程序参数”

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

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


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

【讨论】:

【参考方案9】:

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

【讨论】:

【参考方案10】:

这在 python3 中不起作用,但在 python2 中,您可以使用自定义 __repr__ 方法扩展 str,该方法调用您的 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`

【讨论】:

另外你可能不应该这样做*【参考方案11】:

repr()

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

【讨论】:

这不等同于 bash 反引号。

以上是关于Python中Bash反引号的等价物[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Bash——反引号内的双引号

bash pipestatus 在反引号命令中?

单引号是不是将反斜杠视为 bash 脚本中的特殊字符?

bash中双引号单引号反撇号的用法

Linux shell中,双引号"",单引号'',反引号``之间的区别

linux bash shell中,单引号 双引号,反引号(``)的区别及各种括号的区别