subprocess.getstatusoutput的多平台替代方案是什么?

9 投票
3 回答
5851 浏览
提问于 2025-04-15 13:13

下面的代码在Python 3.0中已经过时,已经被subprocess.getstatusoutput()替代了。

import commands
(ret, out) = commands.getstatusoutput('some command')
print ret
print out

真正的问题是,Python中这个命令在不同平台上有什么替代方案,因为上面的代码在Windows系统下会出错,而getstatusoutput只在Unix系统上支持,Python并不会告诉你这一点,结果你会看到类似这样的错误信息:

>test.py
1
'{' is not recognized as an internal or external command,
operable program or batch file.

3 个回答

1

getstatusoutput 的文档说它是这样运行命令的:

{ cmd } 2>&1

但这显然在 cmd.exe 中不管用(不过如果你需要的话,2>&1 是可以正常工作的)。

你可以像上面那样使用 Popen,但还要加上参数 'stderr=subprocess.STDOUT',这样就能得到和 getstatusoutput 一样的效果。

不过我在 Windows 上测试时,返回码设置为 None,这样就不太理想了,因为如果你依赖返回值的话,这样会有点麻烦。

8

我不太认为这个算是多平台的解决方案,但你可以使用 subprocess.Popen

import subprocess
pipe = subprocess.Popen('dir', stdout=subprocess.PIPE, shell=True, universal_newlines=True)
output = pipe.stdout.readlines()
sts = pipe.wait()
print sts
print output

这里有一个可以替代 getstatusoutput 的方法:

def getstatusoutput(cmd): 
    """Return (status, output) of executing cmd in a shell."""
    """This new implementation should work on all platforms."""
    import subprocess
    pipe = subprocess.Popen(cmd, shell=True, universal_newlines=True,
            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = str.join("", pipe.stdout.readlines()) 
    sts = pipe.wait()
    if sts is None:
        sts = 0
    return sts, output

这个代码片段是原作者提出的。我做了一些修改,因为 getstatusoutput 会把错误信息复制到标准输出里。


问题在于 dir 并不是真正的多平台调用,但 subprocess.Popen 允许你在任何平台上执行命令行指令。我建议你尽量不要使用命令行指令,除非你真的需要。可以先看看 osos.pathshutil 这些模块的内容。

import os
import os.path
for rel_name in os.listdir(os.curdir):
  abs_name = os.path.join(os.curdir, rel_name)
  if os.path.isdir(abs_name):
    print('DIR:  ' + rel_name)
  elif os.path.isfile(abs_name):
    print('FILE: ' + rel_name)
  else:
    print('UNK?  ' + rel_name)
8

这是一个可以在多个平台上使用的 getstatusoutput() 函数的实现:

def getstatusoutput(cmd): 
    """Return (status, output) of executing cmd in a shell."""
    """This new implementation should work on all platforms."""
    import subprocess
    pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, universal_newlines=True)  
    output = "".join(pipe.stdout.readlines()) 
    sts = pipe.returncode
    if sts is None: sts = 0
    return sts, output

撰写回答