将os.system的输出分配给变量,并防止其在屏幕上显示


305

我想将我使用的命令的输出分配给os.system变量,并防止将其输出到屏幕。但是,在下面的代码中,输出将发送到屏幕,并且打印的var值为0,我猜这表明命令是否成功运行。有什么方法可以将命令输出分配给变量,也可以阻止它在屏幕上显示?

var = os.system("cat /etc/services")
print var #Prints 0


4
不要使用os.system(也不os.popen,请按照您接受的答案):使用subprocess.Popen这样更好!
亚历克斯·马丁里

1
@AlexMartelli,一个人不能在subprocess.Popen()中使用复杂的命令(例如管道),但是有了os.system,一个人可以
vak 2015年

2
@vak,您当然可以使用带有&c的管道subprocess.Popen-只需添加即可shell=True
亚历克斯·马蒂利

@AlexMartelli shell=True(通常)是一个非常糟糕的主意!您必须非常确定自己在执行什么:)
IgnacioFernández'16

Answers:


444

从我很久以前问过的“ Python中的Bash反引号等效 ”中,您可能想使用的是popen

os.popen('cat /etc/services').read()

Python 3.6文档中

这是使用subprocess.Popen实现的;有关更强大的方法来管理子流程和与子流程进行通信,请参见该类的文档。


这是对应的代码subprocess

import subprocess

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

6
请注意,subprocess.check_output只要您不关心Walter的解决方案,它似乎就更像是您想要的Pythonic线性代码stderr
chbrown

11
@ChrisBunch为什么suprocess比这更好os.popen
马丁·托马

6
您应该(几乎)永远不要使用shell=True。参见docs.python.org/3/library/…– dylnmc 2014
20:27

44
我不断遇到这个问题,每一次我想知道-为什么最好有三行复杂的代码而不是一行明显的代码?
Ant6n

3
您(几乎)不应该永远不使用shell=True,在这种情况下也不正确。shell=True使得外壳的子进程,而不是cat,所以outerr是的标准输出/标准错误过程而不是的cat过程
villapx

180

您可能还需要查看该subprocess模块,该模块是为替换整个Python popen类型调用系列而构建的。

import subprocess
output = subprocess.check_output("cat /etc/services", shell=True)

它的优点是在调用命令,连接标准输入/输出/错误流等方面具有很大的灵活性。


2
注意到,check_output与蟒蛇2.7添加docs.python.org/2.7/library/...
phyatt

1
此外,还stderr=subprocess.STDOUT可以捕获标准错误
Dolan Antenucci

47

命令模块是执行此操作的合理的高级方法:

import commands
status, output = commands.getstatusoutput("cat /etc/services")

status为0,输出为/ etc / services的内容。


43
命令模块文档中引用:“自2.6版起已弃用:在Python 3中已删除命令模块。请改用子进程模块。”
Cristian Ciupitu

4
确保它已经过时了,但是有时您只想通过几行代码就可以快速,轻松地完成某件事。
anon58192932

5
@advocate签出子流程的check_output命令。快速,简单,并且不会很快贬值!
卢克·史丹利

29

对于python 3.5+,建议您使用subprocess模块​​中run函数。这将返回一个CompletedProcess对象,您可以从该对象轻松获取输出以及返回代码。由于您只对输出感兴趣,因此可以编写这样的实用程序包装。

from subprocess import PIPE, run

def out(command):
    result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True)
    return result.stdout

my_output = out("echo hello world")
# Or
my_output = out(["echo", "hello world"])

不要忘记run()的“ capture_output = True”选项
Elysiumplain

24

我知道已经解决了这个问题,但是我想分享一种通过使用from x import x和函数来调用Popen的可能更好的方法:

from subprocess import PIPE, Popen


def cmdline(command):
    process = Popen(
        args=command,
        stdout=PIPE,
        shell=True
    )
    return process.communicate()[0]

print cmdline("cat /etc/services")
print cmdline('ls')
print cmdline('rpm -qa | grep "php"')
print cmdline('nslookup google.com')

1
3年后,这对我有用。我将其放入一个名为的单独文件中cmd.py,然后在主文件中编写from cmd import cmdline并根据需要使用了它。
Fares KA

1
我在os.system返回0时遇到了同样的问题,但是我尝试了这种方法,效果很好!作为奖励,它看起来很整洁:)谢谢!
Sophie Muspratt

4

我用os.system临时文件来做:

import tempfile,os
def readcmd(cmd):
    ftmp = tempfile.NamedTemporaryFile(suffix='.out', prefix='tmp', delete=False)
    fpath = ftmp.name
    if os.name=="nt":
        fpath = fpath.replace("/","\\") # forwin
    ftmp.close()
    os.system(cmd + " > " + fpath)
    data = ""
    with open(fpath, 'r') as file:
        data = file.read()
        file.close()
    os.remove(fpath)
    return data

1

Python 2.6和3明确表示要避免将PIPE用于stdout和stderr。

正确的方法是

import subprocess

# must create a file object to store the output. Here we are getting
# the ssid we are connected to
outfile = open('/tmp/ssid', 'w');
status = subprocess.Popen(["iwgetid"], bufsize=0, stdout=outfile)
outfile.close()

# now operate on the file
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.