由于 commands 模块自 Python 2.6 以来已弃用,我正在寻找替换commands.getstatusoutput的最佳方法,它返回命令返回代码和输出的元组。subprocess模块相当明显,但是,它不能直接替代 getstatusoutput 。在有关getstatusoutput的相关问题中讨论了一个潜在的解决方案- 但是,我不打算重写原始函数(无论如何,它的 LOC 少于 10 个),但想知道是否有更直接的方法。
问问题
11611 次
3 回答
18
没有直接替换,因为commands.getstatusoutput
是一个糟糕的 API;它结合了 stderr 和 stdout,但没有提供单独检索它们的选项。
您应该使用的便利 API 是subprocess.check_output
,如果命令失败,它将引发异常。
否则,它确实出现了一些缺陷,即subprocess
没有提供在单个调用中检索输出和状态的方法,但它很容易解决;以下是链接问题的答案应该是:
def get_status_output(*args, **kwargs):
p = subprocess.Popen(*args, **kwargs)
stdout, stderr = p.communicate()
return p.returncode, stdout, stderr
如果您想stdout
一起stderr
使用,请使用stderr=subprocess.STDOUT
.
于 2012-07-05T14:05:45.800 回答
9
getstatusoutput 回来了(来自 python 3.1):) 见:http ://docs.python.org/3.3/library/subprocess.html#legacy-shell-invocation-functions
于 2013-04-02T16:53:58.707 回答
0
要回答标题中的问题:这里是基于 asyncio 的getstatusoutput()
实现——它是文档中的代码示例,经过修改以更紧密地遵循subprocess.getstatusoutput()
接口:
import asyncio
import locale
from asyncio.subprocess import PIPE, STDOUT
@asyncio.coroutine
def getstatusoutput(cmd):
proc = yield from asyncio.create_subprocess_shell(cmd,
stdout=PIPE, stderr=STDOUT)
try:
stdout, _ = yield from proc.communicate()
except:
try:
proc.kill()
except ProcessLookupError: # process is already dead
pass
raise
finally:
exitcode = yield from proc.wait()
# return text
output = stdout.decode(locale.getpreferredencoding(False))
# universal newlines mode
output = output.replace("\r\n", "\n").replace("\r", "\n")
if output[-1:] == "\n": # remove a trailing newline
output = output[:-1]
return (exitcode, output)
它适用于 Windows 和 Unix。要运行它(来自同一示例):
import os
from contextlib import closing
if os.name == 'nt': # Windows
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()
with closing(loop):
coro = getstatusoutput('python -m platform')
exitcode, stdout = loop.run_until_complete(coro)
if exitcode == 0:
print("Platform:", stdout)
else:
print("Python failed with exit code %s: %s" % (exitcode, stdout))
于 2014-05-03T14:00:05.963 回答