subprocess.getstatusoutput的多平台替代方案是什么?
下面的代码在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
允许你在任何平台上执行命令行指令。我建议你尽量不要使用命令行指令,除非你真的需要。可以先看看 os
、os.path
和 shutil
这些模块的内容。
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