2010-12-15 60 views
6

En python (sur un système Linux), je lance une commande en utilisant os.system() et en récupérant le code retour. Si ce code retour est différent de 0, je voudrais faire sortir le programme avec ce même code retour. Alors, je l'ai écrit:Comment faire pour contourner la limite de plage de 0-255 pour sys.exit() en python?

ret = os.system(cmd) 
if ret != 0: 
    print "exit with status %s" % ret 
    sys.exit(ret) 

Lorsque le code de retour est inférieur à 256, il fonctionne très bien, mais quand il est supérieur à 255, le code de sortie utilisé est 0. Comment puis-je faire sys.exit() accepte plus de codes de 255?

Edit: la limite est en fait 255

En fait, la variable ret reçoit 256, mais sys.exit() ne parvient pas à l'utiliser, de sorte que le programme renvoie 0 à la place. Lorsque je lance cmd manuellement, je vois qu'il retourne 1, et non 256.

Répondre

0

Works pour moi (CentOS 5.5, Python 2.6.5):

$ python 
>>> import sys 
>>> sys.exit(245) 
$ echo $? 
245 
+0

Ceci n'est pas correct, il ne teste pas la même chose. – unwind

+0

Désolé, mon mauvais, la limite est 255, pas 127. –

+2

La limite 255 est imposée par le shell: http://tldp.org/LDP/abs/html/exit-status.html et http: // tldp. org/LDP/abs/html/exitcodes.html –

2

Vous ne pouvez pas ne devrait pas, car le système réserve des codes de sortie supérieurs à 128 pour lui-même. Si le code retour est compris entre 0 et 127, cela signifie que le programme est sorti de lui-même. Si le code retour est supérieur à 128, cela signifie que le programme a été terminé par un signal système (par exemple SIGKILL ou SIGTERM). Le numéro de signal est le code de résultat moins 128.

Vous devrez le détecter et faire une autre sorte d'indication de sortie, je pense. Peut-être imprimer le code de retour à STDOUT, puis retourner avec 0 (sortie normale, sortie normale) ou 1 (cmd avait une valeur de retour non nulle, la sortie signifie quelque chose).

edit: Apparemment (de this comment), Python est plus intelligent qu'un script shell ... Pour le remettre dans un code de sortie Linux régulière, essayez ceci:

subprocess_exit_code = (ret >> 8) & 0x7f 
subprocess_signal_number = ret & 0xff 

if subpprocess_signal_number == 0: 
    exit_code = subprocess_exit_code 
else: 
    exit_code = 128 + subprocess_signal_number 

Bien que cela ne tient pas compte du core- vider l'information.

5

En fait, le documentation indique que

état de sortie indicatif: un nombre de 16 bits, dont l'octet de poids faible est le nombre de signaux qui a tué le processus, et dont octet de poids fort est l'état de sortie (si le signal le nombre est zéro); le bit haut de l'octet bas est défini si un fichier core a été produit.

donc je dois traiter le nombre retourné par sys.exit() afin de récupérer l'état de sortie réelle, comme ceci:

ret = os.system(cmd) 
# Ignore the first byte, use the second one only 
ret = ret >> 8 
if ret != 0: 
    print "exit with status %s" % ret 
    sys.exit(ret) 

Et maintenant, il fonctionne: ret contient 1 au lieu de 256

+0

Oh. Je viens de commencer à me demander pourquoi il renvoie 0x8b00 sur segfaulty terminaison. – ulidtko

+0

Je pense que si elle déverse le noyau qui vous donnera un code de sortie différent de ce que vous auriez si vous l'avez exécuté à partir de la ligne de commande. –

+1

vous pouvez utiliser 'subprocess.call' au lieu de' os.system': comparer 'python -c 'import os; print [os.system (["./ exit-with ", str (i)]) pour i dans [127,128,255,256,257]] '' et sous-processus d'importation' python -c ' print [subprocess.call (["./ exit-with", str (i)]) pour i dans [127,128,255,256,257]] ''où' exit-with' est http://ideone.com/zFelC – jfs