15

由于 commands 模块自 Python 2.6 以来已弃用,我正在寻找替换commands.getstatusoutput的最佳方法,它返回命令返回代码和输出的元组。subprocess模块相当明显,但是,它不能直接替代 getstatusoutput 在有关getstatusoutput的相关问题中讨论了一个潜在的解决方案- 但是,我不打算重写原始函数(无论如何,它的 LOC 少于 10 个),但想知道是否有更直接的方法。

4

3 回答 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 回答