如何解读Python中commands.getstatusoutput()的状态码
在一个相关的问题中,我问过在哪里可以找到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 个回答
看一下 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。
强调一下,这是我自己的看法。我同意这种“编码”方式不是特别直观,但至少一眼看过去就能明白它是在进行乘法或位移操作。
哇,原来是乘以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')
在 os
模块里,有一组函数,比如 os.WIFCONTINUED
、os.WIFSTOPPED
、os.WTERMSIG
、os.WCOREDUMP
、os.WIFEXITED
、os.WEXITSTATUS
、os.WIFSIGNALED
和 os.WSTOPSIG
,这些函数对应于 wait(2) 手册中的一些宏。你可以用它们来解读状态码。
举个例子,如果你想获取退出代码,就可以使用 os.WEXITSTATUS(status)
。
不过,更好的做法是使用 subprocess
模块。