2010-12-15 8 views
6

W pythonie (w systemie Linux) uruchamiam polecenie, używając os.system() i odzyskując kod powrotu. Jeśli ten kod powrotu jest inny niż 0, chciałbym, aby program zakończył działanie z tym samym kodem powrotu. Więc napisałem:Jak ominąć limit zasięgu 0-255 dla sys.exit() w pythonie?

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

Gdy kod powrotu jest niższa niż 256, to działa dobrze, ale gdy jest większa niż 255, kod wyjścia używany jest 0. W jaki sposób mogę dokonać sys.exit() akceptuje kody większa niż 255?

Edit: limit jest faktycznie 255

W rzeczywistości, zmienna ret otrzyma 256, ale sys.exit() zawiedzie go używać, więc program zwraca 0 zamiast. Kiedy uruchomić cmd ręcznie, widzę, że zwraca 1, a nie 256.

Odpowiedz

0

pracuje dla mnie (CentOS 5.5, Python 2.6.5):

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

To nie jest poprawne, nie testuje tego samego. – unwind

+0

Niestety, mój zły, limit wynosi 255, a nie 127. –

+2

Limit 255 jest wymuszany przez powłokę: http://tldp.org/LDP/abs/html/exit-status.html i http: // tldp. org/LDP/abs/html/exitcodes.html –

2

Ty nie może nie powinien, ponieważ system rezerwuje dla siebie kody wyjścia powyżej 128. Jeśli kod powrotu ma wartość od 0 do 127, oznacza to, że program zakończył się sam. Jeśli kod powrotu jest wyższy niż 128, oznacza to, że program został zakończony przez sygnał systemowy (na przykład SIGKILL lub SIGTERM). Numer sygnału jest kodem wynikowym minus 128.

Musisz go wykryć i zrobić jakieś inne wskazanie wyjścia, jak sądzę. Być może wydrukuj kod powrotu do STDOUT, a następnie powróć z 0 (normalne wyjście, normalne wyjście) lub 1 (cmd ma niezerową wartość zwracaną, wyjście oznacza coś).

edit: Podobno (od this comment), Python jest mądrzejszy niż skryptu powłoki ... Aby umieścić go z powrotem do regularnego Linux kod wyjścia, spróbuj tego:

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 

Chociaż ta ignoruje rdzeniowe zrzutu informacji.

5

Właściwie documentation wskazuje, że wskazania

wyjścia Status: A liczba 16-bitowa, której niski bajt jest numer sygnału, który zabił proces, a którego bajt jest kod zakończenia (jeśli sygnał liczba to zero); wysoki bit niskiego bajtu jest ustawiony, jeśli został utworzony plik core.

Więc muszę przetworzyć liczbę zwracanych przez sys.exit() w celu pobrania rzeczywisty stan wyjścia, jak w przykładzie:

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) 

A teraz to działa: ret zawiera 1 zamiast 256

+0

Oh. Właśnie zacząłem się zastanawiać, dlaczego zwraca 0x8b00 na zakończenie segregacji. – ulidtko

+0

Myślę, że jeśli zrzuci rdzeń, który da inny kod zakończenia do tego, co masz, jeśli uruchomisz go z wiersza poleceń. –

+1

możesz użyć 'subprocess.call' zamiast' os.system': porównaj 'python -c 'import os; print [os.system (["./ exit-with ", str (i)]) dla i w [127, 128, 255, 255, 257]] podprocesie' 'i' python -c 'import print [subprocess.call (["./ exit-with", str (i)]) dla i w [127,128,255,256,257]] ''gdzie' exit-with' jest http://ideone.com/zFelC – jfs

Powiązane problemy