Jak wyjść z Pythona bez śledzenia?


277

Chciałbym wiedzieć, jak wyjść z Pythona bez zrzutu zrzutu danych wyjściowych.

Nadal chcę, aby móc zwrócić kod błędu, ale nie chcę wyświetlać dziennika śledzenia.

Chcę móc wyjść exit(number)bez śledzenia, ale w przypadku wyjątku (nie wyjścia) chcę śledzenia.


8
sys.exit () zatrzymuje wykonywanie bez drukowania śladu wstecznego, zgłoszenie wyjątku robi ... twoje pytanie dokładnie opisuje domyślne zachowanie, więc niczego nie zmieniaj.
Luper Rouch

@Luper Bardzo łatwo jest sprawdzić, czy sys.exit () wyrzuca SystemExit!
Val

4
Powiedziałem, że nie drukuje śledzenia, nie dlatego, że nie podnosi wyjątku.
Luper Rouch

Myślę, że to naprawdę odpowiada na pytanie, które zadałeś: stackoverflow.com/questions/173278/...
Stefan,

2
Czy to pytanie dotyczy Jython 2.4, czy coś takiego? Ponieważ w przypadku nowoczesnych wersji Pythona (nawet w 2009 roku, kiedy oznaczało to CPython 2.6 i 3.1, Jython 2.5 i IronPython 2.6), pytanie nie ma sensu, a najlepsze odpowiedzi są błędne.
abarnert

Odpowiedzi:


300

Prawdopodobnie napotykasz wyjątek, a program wychodzi z tego powodu (z funkcją śledzenia). Pierwszą rzeczą, którą należy zrobić, to złapać ten wyjątek, zanim wyjdzie on czysto (może z komunikatem, podanym przykładem).

Wypróbuj coś takiego w swojej mainrutynie:

import sys, traceback

def main():
    try:
        do main program stuff here
        ....
    except KeyboardInterrupt:
        print "Shutdown requested...exiting"
    except Exception:
        traceback.print_exc(file=sys.stdout)
    sys.exit(0)

if __name__ == "__main__":
    main()

2
Na początku powinno być coś w rodzaju „from sys import exit”.
okradać

10
Jeśli sys.exit () jest wywoływany w „głównym programie”, powyższy kod odrzuca wartość przekazywaną do sys.exit. Zauważ, że sys.exit podnosi SystemExit, a zmienna „e” będzie zawierała kod wyjścia.
bstpierre

5
sugerowałbym drukowanie w stderr sys.stderr.write (msg)
vinilios

14
I silnie sugerują, usuwanie linii od except Exception:do sys.exit(0)włącznie. Jest to już domyślne zachowanie, aby wydrukować śledzenie wszystkich nieobsługiwanych wyjątków i wyjść po zakończeniu kodu, więc po co męczyć się z tym samym ręcznie?
MestreLion,

6
@jkp - W odniesieniu do komentarza: sys.exit()należy stosować w przypadku programów. exit()jest przeznaczony do interaktywnych powłok. Zobacz Różnica między exit () a sys.exit () w Pythonie? .
ire_and_curses 16.01.2013

81

Być może próbujesz uchwycić wszystkie wyjątki, a to łapie SystemExitwyjątek zgłoszony przez sys.exit()?

import sys

try:
    sys.exit(1) # Or something that calls sys.exit()
except SystemExit as e:
    sys.exit(e)
except:
    # Cleanup and reraise. This will print a backtrace.
    # (Insert your cleanup code here.)
    raise

Ogólnie rzecz biorąc, używanie except:bez nazewnictwa wyjątków jest złym pomysłem. Złapiesz wszystkie rzeczy, których nie chcesz - na przykład SystemExit- i może również maskować własne błędy programistyczne. Mój przykład powyżej jest głupi, chyba że robisz coś w zakresie czyszczenia. Możesz go zastąpić:

import sys
sys.exit(1) # Or something that calls sys.exit().

Jeśli musisz wyjść bez podnoszenia SystemExit:

import os
os._exit(1)

Robię to w kodzie, który działa w trybie unittest i wywołuje fork(). Unittest dostaje się, gdy rozwidla się proces SystemExit. To zdecydowanie przypadek narożny!


4
-1: Ten kod jest głupi: SystemExitpo co łapać, żeby zadzwonić sys.exit(e)? Usunięcie obu linii ma ten sam efekt. Ponadto, należy do czyszczenia finally:, nie except Exception: ... raise.
MestreLion,

@MestreLion: Możesz swobodnie głosować, ale jeśli przeczytasz mój komentarz tuż nad twoim, to dotyczy to tylko wersji 2.5+. Jeśli przeczytałeś cały mój post, wyraźnie powiedziałem, że kod jest głupi i zasugerowałem dokładnie to, co powiedziałeś w swoim komentarzu.
bstpierre

2
Przepraszamy, masz rację ... Zapomniałem, że w Pythonie 2.5 nastąpiła poważna reorganizacja wyjątków. Próbowałem cofnąć głosowanie negatywne, ale SO pozwala mi to zrobić tylko wtedy, gdy odpowiedź jest edytowana. Skoro jesteśmy w 2012 roku, a Python 2.4 to starożytna historia, dlaczego nie edytować go i pokazać z góry poprawny (aktualny) kod, pozostawiając metodę wcześniejszą niż 2.5 jako przypis? To znacznie poprawi odpowiedź i będę mógł cofnąć głosowanie i chętnie to zrobię. Win-win dla wszystkich :)
MestreLion,

@MestreLion: Zacząłem edytować tak, jak sugerowałeś, ale ta odpowiedź naprawdę ma sens tylko w kontekście pytania i środowiska 2.4. Głos nie denerwuje mnie.
bstpierre,


9

coś jak import sys; sys.exit(0)?


@mestreLion Więc dlaczego dostaję Dets 06 18:53:17 Traceback (ostatnie ostatnie połączenie): Plik „debug_new.py”, wiersz 4, w <module> import sys; sys.exit (0) SystemExit: 0 at org.python.core.PyException.fillInStackTrace (PyException.java:70) w mojej konsoli?
Val

3
@ Val: ponieważ nie używasz standardowej konsoli python. Jython nie jest Pythonem i wygląda na to, że (lub przynajmniej jego konsola) obsługuje wyjątki inaczej.
MestreLion,



4

O wiele lepszą praktyką jest unikanie używania sys.exit () i zamiast tego podnoszenie / obsługa wyjątków, aby umożliwić programowi dokładne zakończenie. Jeśli chcesz wyłączyć śledzenie, po prostu użyj:

sys.trackbacklimit=0

Możesz ustawić to u góry skryptu, aby zmiażdżyć wszystkie dane wyjściowe śledzenia, ale wolę używać go bardziej oszczędnie, na przykład „znane błędy”, w których chcę, aby dane wyjściowe były czyste, np. W pliku foo.py:

import sys
from subprocess import *

try:
  check_call([ 'uptime', '--help' ])
except CalledProcessError:
  sys.tracebacklimit=0
  print "Process failed"
  raise

print "This message should never follow an error."

Jeśli zostanie złapany CalledProcessError, dane wyjściowe będą wyglądać następująco:

[me@test01 dev]$ ./foo.py
usage: uptime [-V]
    -V    display version
Process failed
subprocess.CalledProcessError: Command '['uptime', '--help']' returned non-zero exit status 1

Jeśli wystąpi jakikolwiek inny błąd, nadal otrzymujemy pełne dane wyjściowe śledzenia.


1
Aby korzystać sys.trackbacklimitz Python 3, zobacz tę odpowiedź .
Acumenus,

4

Użyj wbudowanej funkcji pyton quit () i to wszystko. Nie trzeba importować żadnej biblioteki. Używam Pythona 3.4


2

Zrobiłbym to w ten sposób:

import sys

def do_my_stuff():
    pass

if __name__ == "__main__":
    try:
        do_my_stuff()
    except SystemExit, e:
        print(e)

0

Co powiesz na

import sys
....
....
....
sys.exit("I am getting the heck out of here!")

Bez śledzenia i jakoś bardziej jednoznacznie.


-8
# Pygame Example  

import pygame, sys  
from pygame.locals import *

pygame.init()  
DISPLAYSURF = pygame.display.set_mode((400, 300))  
pygame.display.set_caption('IBM Emulator')

BLACK = (0, 0, 0)  
GREEN = (0, 255, 0)

fontObj = pygame.font.Font('freesansbold.ttf', 32)  
textSurfaceObj = fontObj.render('IBM PC Emulator', True, GREEN,BLACK)  
textRectObj = textSurfaceObj.get_rect()  
textRectObj = (10, 10)

try:  
    while True: # main loop  
        DISPLAYSURF.fill(BLACK)  
        DISPLAYSURF.blit(textSurfaceObj, textRectObj)  
        for event in pygame.event.get():  
            if event.type == QUIT:  
                pygame.quit()  
                sys.exit()  
        pygame.display.update()  
except SystemExit:  
    pass

7
Jeśli skomentujesz kod, poprawi to jakość odpowiedzi.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.