溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

【python2】commands模塊getstatusoutput函數(shù)的小問(wèn)題

發(fā)布時(shí)間:2020-07-08 21:37:03 來(lái)源:網(wǎng)絡(luò) 閱讀:3367 作者:對(duì)唔住 欄目:編程語(yǔ)言

[TOC]

問(wèn)題

import commands as subprocess
status, _ = subprocess.getstatusoutput("ps -elf|grep fuckU")
# status:
# 255
  • 這里的status按照grep的定義其實(shí)應(yīng)該返回1,也就是沒(méi)有g(shù)rep到匹配項(xiàng),在shell中echo $? 結(jié)果為1
    但是python2getstatusoutput獲取的并不是os.exitcode()而是os.wait()的返回值。

  • python3由于使用的是subprocess = modified(commands + subprocess),同樣執(zhí)行
    status, _ = subprocess.getstatusoutput("ps -elf|grep fuckU")

    得到的status為正確的1

我是怎么解決這個(gè)問(wèn)題

兼顧Python2和Python3的使用習(xí)慣,使用google開(kāi)源的subprocess32代替commands

什么是subprocess32

谷歌將Python32的subprocess移植到了python2版本中。據(jù)說(shuō)這是線程安全的版本。
最新的Python32版本為3.5.3也就是將python3.5.3中的subprocess基本功能移植到了Python2中。但是subprocess32不包含原本commands中的函數(shù)。

Timeout support backported from Python 3.3 is included.
The run() API from Python 3.5 was backported in subprocess32 3.5.0.
Otherwise features are frozen at the 3.2 level.

這里我們使用subprocess32.run()方法去模擬getstatusoutput等便捷的函數(shù)(python3官方實(shí)現(xiàn))

# 原本的timeout=None,因?yàn)镻ython2不支持*args,**kwargs外再有kwargs,暫時(shí)移出參數(shù)項(xiàng),放至函數(shù)體內(nèi)
# def check_output(*popenargs, timeout=None, **kwargs):
def check_output(*popenargs, **kwargs):
    r"""Run command with arguments and return its output.

    If the exit code was non-zero it raises a CalledProcessError.  The
    CalledProcessError object will have the return code in the returncode
    attribute and output in the output attribute.

    The arguments are the same as for the Popen constructor.  Example:

    >>> check_output(["ls", "-l", "/dev/null"])
    b'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'

    The stdout argument is not allowed as it is used internally.
    To capture standard error in the result, use stderr=STDOUT.

    >>> check_output(["/bin/sh", "-c",
    ...               "ls -l non_existent_file ; exit 0"],
    ...              stderr=STDOUT)
    b'ls: non_existent_file: No such file or directory\n'

    There is an additional optional argument, "input", allowing you to
    pass a string to the subprocess's stdin.  If you use this argument
    you may not also use the Popen constructor's "stdin" argument, as
    it too will be used internally.  Example:

    >>> check_output(["sed", "-e", "s/foo/bar/"],
    ...              input=b"when in the course of fooman events\n")
    b'when in the course of barman events\n'

    If universal_newlines=True is passed, the "input" argument must be a
    string and the return value will be a string rather than bytes.
    """
    timeout = None
    if 'stdout' in kwargs:
        raise ValueError('stdout argument not allowed, it will be overridden.')

    if 'input' in kwargs and kwargs['input'] is None:
        # Explicitly passing input=None was previously equivalent to passing an
        # empty string. That is maintained here for backwards compatibility.
        kwargs['input'] = '' if kwargs.get('universal_newlines', False) else b''

    return subprocess.run(*popenargs, stdout=subprocess.PIPE, timeout=timeout, check=True,
                          **kwargs).stdout

def getstatusoutput(cmd):
    """Return (exitcode, output) of executing cmd in a shell.

    Execute the string 'cmd' in a shell with 'check_output' and
    return a 2-tuple (status, output). The locale encoding is used
    to decode the output and process newlines.

    A trailing newline is stripped from the output.
    The exit status for the command can be interpreted
    according to the rules for the function 'wait'. Example:

    >>> import subprocess
    >>> subprocess.getstatusoutput('ls /bin/ls')
    (0, '/bin/ls')
    >>> subprocess.getstatusoutput('cat /bin/junk')
    (1, 'cat: /bin/junk: No such file or directory')
    >>> subprocess.getstatusoutput('/bin/junk')
    (127, 'sh: /bin/junk: not found')
    >>> subprocess.getstatusoutput('/bin/kill $$')
    (-15, '')
    """
    try:
        data = check_output(cmd, shell=True, universal_newlines=True, stderr=subprocess.STDOUT)
        exitcode = 0
    except subprocess.CalledProcessError as ex:
        data = ex.output
        exitcode = ex.returncode
    if data[-1:] == '\n':
        data = data[:-1]
    return exitcode, data

def getoutput(cmd):
    """Return output (stdout or stderr) of executing cmd in a shell.

    Like getstatusoutput(), except the exit status is ignored and the return
    value is a string containing the command's output.  Example:

    >>> import subprocess
    >>> subprocess.getoutput('ls /bin/ls')
    '/bin/ls'
    """
    return getstatusoutput(cmd)[1]

題外話

其實(shí)python官方推薦使用這個(gè)函數(shù)執(zhí)行系統(tǒng)命令
subprocess.run()

但是這個(gè)函數(shù)將輸出直接print到終端中

如果需要屏蔽恣意的屏幕輸出,可以使用subprocess.DEVNULL (subprocess 3.5.3中有)

# 即
x = subprocess.run('echo 250', shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
# x:
# CompletedProcess(args='echo 250', returncode=0)

# reference: https://stackoverflow.com/questions/8529390/is-there-a-quiet-version-of-subprocess-call
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI