2009-10-08 23 views
5

En un related question, pregunté dónde encontrar la documentación para la función C "esperar". Este fue un intento de averiguar los códigos de retorno para el módulo commands.getstatusoutput(). Stackoverflow llegó, pero la documentación no ayudó. Esto es lo que me intriga:Cómo interpretar el código de estado en Python commands.getstatusoutput()

#!/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) 

cuando se ejecuta en OS X (Leopard) me sale el siguiente resultado: (. Lo cual coincide con la documentación)

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

En OS X, haciendo un "ls/Falla ; echo $? " obtiene el siguiente resultado:

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

Cuando se ejecuta en Linux (Ubuntu Hardy) me sale el siguiente resultado:

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

En Ubuntu, haciendo "ls/no pasa" consigue un 2:

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

Así que Python parece estar multiplicando códigos de estado por 256. ¿Eh? ¿Está esto documentado en alguna parte?

+0

la [respuesta por @Schof] (http://stackoverflow.com/a/1535675/52074) responde a la pregunta "cuando se utiliza' commands.getstatusoutput() '¿por qué los códigos de salida se multiplican por 256?" directamente y con código de ejemplo. Las otras dos respuestas dicen más o menos "use' subprocess' en lugar de 'commands.getstatusoutput()' "o" aquí se explica cómo usar subprocess ". –

Respuesta

10

hay un conjunto de funciones en os módulo (os.WIFCONTINUED, os.WIFSTOPPED, os.WTERMSIG, os.WCOREDUMP, os.WIFEXITED, os.WEXITSTATUS, os.WIFSIGNALED, os.WSTOPSIG), que corresponden a las macros de wait(2) manual. Debe usarlos para interpretar el código de estado.

Por ejemplo, para obtener el código de salida se debe utilizar os.WEXITSTATUS(status)

Una mejor idea sería cambiar a subprocess módulo.

4

Wow. La idea de que se estaba multiplicando por 256 me llevó allí. La búsqueda de "comandos de Python +256" me llevó a un artículo Python Module Of The Week que explica lo que está sucediendo.

He aquí un fragmento de esa página:

La función getstatusoutput() se ejecuta un comando a través de la cáscara y devuelve el código salida y el texto de salida (stdout y stderr combinado). Los códigos de salida son los mismos que para la función C wait() o os.wait(). El código es un número de 16 bits . El byte bajo contiene el número de señal que mató al proceso . Cuando la señal es cero, el byte alto es el estado de salida del programa . Si se produjo un archivo central, se establece el bit alto del byte bajo.

Y algunos de código de 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') 
+0

el retorno de os.system (cmd) parece funcionar de la misma manera 'idea de que se estaba multiplicando por 256' – CaffeineAddiction

3

En cuanto a 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 

Vemos sts mantiene el valor de os.popen(...).close(). En cuanto a that documentationos.popen(...).close(), devuelve el valor de os.wait:

os.wait()

Esperar a la finalización de un proceso hijo, y devolver una tupla que contiene su indicación PID y el código de salida: un número de 16 bits, cuya baja byte es el número de señal que mató el proceso, y cuyo byte alto es el estado de salida (si el número de señal es cero); el bit alto del byte bajo se establece si se produjo un archivo core. Disponibilidad: Unix.

El énfasis era mío. Estoy de acuerdo en que esta "codificación" no es terriblemente intuitiva, pero al menos era bastante obvio a simple vista que se estaba multiplicando/desplazando bits.

+0

Gracias por el énfasis, estaba bastante confundido por lo que estaba viendo hasta que leí esto ... –

0

Creo que la detección del código es incorrecta.

"Si se produjo un archivo de núcleo, se establece el bit alto del byte bajo". significa 128.

así que creo que la línea central debe ser

print 'Core? : %s' % bool(status & 128) 
Cuestiones relacionadas