如何解读Python中commands.getstatusoutput()的状态码

7 投票
4 回答
17591 浏览
提问于 2025-04-15 14:54

在一个相关的问题中,我问过在哪里可以找到C语言函数“wait”的文档。我想弄清楚commands.getstatusoutput()模块的返回代码。Stackoverflow给了我答案,但文档并没有帮助我。让我感到困惑的是:

#!/usr/bin/python
import commands
goodcommand = 'ls /'
badcommand = 'ls /fail'
status, output = commands.getstatusoutput(goodcommand)
print('Good command reported status of %s' % status)
status, output = commands.getstatusoutput(badcommand)
print('Bad command reported status of %s' % status)

在OS X(Leopard)上运行时,我得到了以下输出:(这和文档上说的一样。)

$ python waitest.py 
Good command reported status of 0
Bad command reported status of 256

在OS X上,执行“ls /fail ; echo $?”会得到以下输出:

$ ls /fail ; echo $?
ls: /fail: No such file or directory
1

在Linux(Ubuntu Hardy)上运行时,我得到了以下输出:

$ python waitest.py 
Good command reported status of 0
Bad command reported status of 512

在Ubuntu上,执行“ls /fail”会得到2:

$ ls /fail ; echo $?
ls: cannot access /fail: No such file or directory
2

所以Python似乎把状态码乘以了256。这是怎么回事?这个问题在文档里有说明吗?

4 个回答

3

看一下 commands.py 文件:

def getstatusoutput(cmd):
    """Return (status, output) of executing cmd in a shell."""
    import os
    pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
    text = pipe.read()
    sts = pipe.close()
    if sts is None: sts = 0
    if text[-1:] == '\n': text = text[:-1]
    return sts, text

我们看到 sts 保存了 os.popen(...).close() 的值。根据这个文档os.popen(...).close() 返回的是 os.wait 的值:

os.wait()

这个函数会等待一个子进程完成,并返回一个包含它的进程ID(pid)和退出状态的元组:这是一个16位的数字,低字节部分是终止这个进程的信号编号,而高字节部分是退出状态(如果信号编号为零的话);如果产生了核心文件,低字节的高位会被设置。适用平台:Unix。

强调一下,这是我自己的看法。我同意这种“编码”方式不是特别直观,但至少一眼看过去就能明白它是在进行乘法或位移操作。

4

哇,原来是乘以256让我明白了这个问题。搜索“python 命令 +256”让我找到了一个Python每周模块的文章,里面解释了发生了什么。

这里是那篇文章中的一小段:

函数getstatusoutput()通过命令行运行一个命令,并返回退出代码和文本输出(标准输出和错误输出合在一起)。退出代码和C语言中的wait()或os.wait()函数是一样的。这个代码是一个16位的数字。低字节包含了终止进程的信号编号。当信号为零时,高字节就是程序的退出状态。如果产生了核心文件,低字节的高位会被设置。

还有Doug的一些代码:

from commands import *

def run_command(cmd):
    print 'Running: "%s"' % cmd
    status, text = getstatusoutput(cmd)
    exit_code = status >> 8
    signal_num = status % 256
    print 'Signal: %d' % signal_num
    print 'Exit  : %d' % exit_code
    print 'Core? : %s' % bool(exit_code / 256)
    print 'Output:'
    print text
    print

run_command('ls -l *.py')
run_command('ls -l *.notthere')
run_command('echo "WAITING TO BE KILLED"; read input')
11

os 模块里,有一组函数,比如 os.WIFCONTINUEDos.WIFSTOPPEDos.WTERMSIGos.WCOREDUMPos.WIFEXITEDos.WEXITSTATUSos.WIFSIGNALEDos.WSTOPSIG,这些函数对应于 wait(2) 手册中的一些宏。你可以用它们来解读状态码。

举个例子,如果你想获取退出代码,就可以使用 os.WEXITSTATUS(status)

不过,更好的做法是使用 subprocess 模块。

撰写回答