Python: 如何在运行 os.system 之后获得 stdout?

在运行 os.system调用之后,我想在一个变量中获得 stdout

让我们以这一行为例:

batcmd="dir"
result = os.system(batcmd)

result将包含错误代码(对于上面的示例,在 Windows 下的 stderr0或在某个 Linux 下的 1)。

如何在不使用执行命令中的重定向的情况下获得上述命令的 stdout

276892 次浏览

如果你所需要的只是 stdout的输出,那么看看 subprocess.check_output():

import subprocess


batcmd="dir"
result = subprocess.check_output(batcmd, shell=True)

因为您使用的是 os.system(),所以必须设置 shell=True才能得到相同的行为。您确实需要注意 安全问题关于向 shell 传递不可信参数的说明。

如果还需要捕获 stderr,只需将 stderr=subprocess.STDOUT添加到调用中:

result = subprocess.check_output([batcmd], stderr=subprocess.STDOUT)

将错误输出重定向到默认输出流。

如果您知道输出是文本,那么添加 text=True以使用平台默认编码对返回的字节值进行解码; 如果接收到的数据的解码器不正确,则使用 encoding="..."

我想详细介绍一下 Windows 解决方案。在 Python 2.7.5中使用 IDLE,当我从 Exts.py 文件运行这段代码时:

import subprocess
r = subprocess.check_output('cmd.exe dir',shell=False)
print r

... 在 Python Shell 中,我只获得对应于“ cmd.exe”的输出; “ dir”部分被忽略。然而,当我添加一个开关,如/K 或/C..。

import subprocess
r = subprocess.check_output('cmd.exe /K dir',shell=False)
print r

然后在 Python Shell 中,我得到了所有我想要的,包括目录列表!

现在,如果我在 DOS Python 命令窗口中尝试任何相同的操作,不使用开关,或者使用/K 开关,那么窗口看起来会挂起,因为它正在运行一个子进程 cmd.exe,等待进一步的输入类型‘ exit’,然后点击[ enter ]发布。但是使用/K 开关它可以很好地工作,并返回到 python 提示符。那好吧。

更进一步... 我认为这很酷... 当我在 Exts.py 中这样做时:

import subprocess
r = subprocess.call("cmd.exe dir",shell=False)
print r

... 一个新的 DOS 窗口弹出并保持只显示“ cmd.exe”而不是“ dir”的结果。当我添加/C 开关时,DOS 窗口会在我看到任何东西之前快速打开和关闭(正如预期的那样,因为/C 在完成时终止)。当我添加/K 开关时,DOS 窗口弹出并保持打开状态,并且我得到所有我期望的输出,包括目录列表。

如果我在 DOS Python 命令窗口中尝试相同的操作(subprocess.call 而不是 subprocess.check _ output) ; 所有的输出都在同一个窗口中,不会出现弹出窗口。如果没有这个开关,“ dir”部分将再次被忽略,并且提示符将从 python 提示符更改为 DOS 提示符(因为在 python 中运行的是 cmd.exe 子进程; 再次键入‘ exit’,您将恢复到 python 提示符)。添加/K 开关会打印出目录清单并将提示从 python 更改为 DOS,因为/K 并不终止子进程。将开关更改为/C 会将所有预期的输出 AND 返回到 python 提示符,因为子进程按照/C 终止。

对于冗长的回答,我很抱歉,但是我对这个版块上的许多简短的“答案”感到沮丧,这些答案充其量是不起作用的(似乎是因为它们没有被测试——就像爱德华 · F 的回答在我的上面,缺少开关)或者更糟糕的是,它们如此简短,以至于它们根本没有多大帮助(例如,“尝试子进程而不是 os.system”... ... 是的,好吧,现在怎么办.相比之下,我提供了我测试过的解决方案,并展示了它们之间的细微差别。花了很多时间,但是..。 希望这个能帮上忙。

这些答案对我不起作用,我不得不使用以下方法:

import subprocess
p = subprocess.Popen(["pwd"], stdout=subprocess.PIPE)
out = p.stdout.read()
print out

或者作为一个函数(在 Python 2.6.7上使用 shell = True 对我来说是必需的,并且 check _ output 直到2.7才被添加,这使得它在这里不可用) :

def system_call(command):
p = subprocess.Popen([command], stdout=subprocess.PIPE, shell=True)
return p.stdout.read()

commands也可以。

import commands
batcmd = "dir"
result = commands.getoutput(batcmd)
print result

它可以在 linux,python 2.7上运行。

我不得不使用 os.system,因为子进程为较大的任务提供了一个内存错误。这个问题的参考资料。因此,为了得到 os.system 命令的输出,我使用了下面这个变通方法:

import os


batcmd = 'dir'
result_code = os.system(batcmd + ' > output.txt')
if os.path.exists('output.txt'):
fp = open('output.txt', "r")
output = fp.read()
fp.close()
os.remove('output.txt')
print(output)
import subprocess
string="echo Hello world"
result=subprocess.getoutput(string)
print("result::: ",result)