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.stdout
和 cpe.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反引号的等价物[重复]的主要内容,如果未能解决你的问题,请参考以下文章