Python 中的 Ruby 和 Perl 中的反引号等价物是什么?也就是说,在 Ruby 中我可以这样做:
foo = `cat /tmp/baz`
Python 中的等效语句是什么样的?我已经尝试过os.system("cat /tmp/baz")
,但这会将结果标准化并返回给我该操作的错误代码。
output = os.popen('cat /tmp/baz').read()
最灵活的方式是使用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 执行程序*
,但这有限制。
某事是对的。您也可以使用 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))
foo = subprocess.check_output(["cat", "/tmp/baz"])
从 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.stdout
和cpe.stderr
都是str
对象。
最简单的方法是使用命令包。
import commands
commands.getoutput("whoami")
输出:
'bganesan'
import os
foo = os.popen('cat /tmp/baz', 'r').read()
我在用着
(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 使这变得合理。
这在 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`
如果使用 subprocess.Popen,请记住指定 bufsize。默认值为 0,表示“无缓冲”,而不是“选择合理的默认值”。