Como sair do Python sem rastreamento?

277

Gostaria de saber como sair do Python sem ter um despejo de traceback na saída.

Ainda quero poder retornar um código de erro, mas não quero exibir o log de rastreamento.

Quero poder sair usando exit(number)sem rastreamento, mas no caso de uma exceção (não uma saída), quero o rastreamento.

sorin
fonte
8
sys.exit () interrompe a execução sem imprimir um backtrace, gerando uma exceção ... sua pergunta descreve exatamente qual é o comportamento padrão, portanto, não altere nada.
Luper Rouch
@ Super É muito fácil verificar se sys.exit () lança SystemExit!
Val
4
Eu disse que não imprime um rastreio, não que isso não gera uma exceção.
Luper Rouch
Eu acho que isso realmente responde à pergunta que você fez: stackoverflow.com/questions/173278/...
Stefan
2
Esta pergunta é específica para o Jython 2.4 ou algo parecido? Porque nas versões modernas do Python (mesmo em 2009, quando isso significava o CPython 2.6 e 3.1, Jython 2.5 e IronPython 2.6), a pergunta não faz sentido e as principais respostas estão erradas.
abarnert

Respostas:

300

Você provavelmente está encontrando uma exceção e o programa está saindo por causa disso (com um rastreamento). A primeira coisa a fazer, portanto, é capturar essa exceção, antes de sair corretamente (talvez com uma mensagem, exemplo dado).

Tente algo como isso em sua mainrotina:

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()
jkp
fonte
2
Deve haver algo como "from sys import exit" no começo.
27410 rob
10
Se sys.exit () for chamado em "itens principais do programa", o código acima jogará fora o valor passado para sys.exit. Observe que o sys.exit gera SystemExit e a variável "e" conterá o código de saída.
22289 bstpierre
5
eu sugeriria a impressão em stderr sys.stderr.write (msg)
vinilios
14
Eu sugiro fortemente remover as linhas de except Exception:para sys.exit(0), inclusive. Já é o comportamento padrão imprimir um retorno em todas as exceções não tratadas e sair após o término do código, por que se preocupar em fazer o mesmo manualmente?
MestreLion
6
@jkp - Em relação ao seu comentário: sys.exit()deve ser usado para programas. exit()destina-se a conchas interativas. Veja A diferença entre exit () e sys.exit () no Python? .
ire_and_curses
81

Talvez você esteja tentando capturar todas as exceções e isso está capturando a SystemExitexceção criada por 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

Em geral, usar except:sem nomear uma exceção é uma má ideia. Você pega todos os tipos de coisas que não deseja capturar - como SystemExit- e também pode mascarar seus próprios erros de programação. Meu exemplo acima é bobo, a menos que você esteja fazendo algo em termos de limpeza. Você pode substituí-lo por:

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

Se você precisar sair sem aumentar SystemExit:

import os
os._exit(1)

Eu faço isso, no código que é executado sob unittest e chama fork(). O Unittest fica quando o processo bifurcado aumenta SystemExit. Este é definitivamente um caso de canto!

bstpierre
fonte
4
-1: esse código é bobo: por que pegar SystemExitapenas para ligar sys.exit(e)? A remoção das duas linhas tem o mesmo efeito. Além disso, a limpeza pertence a finally:, não except Exception: ... raise.
MestreLion
@MestreLion: Você é livre para votar, mas se você ler o meu comentário logo acima do seu, isso é verdade apenas para 2.5+. Se você leu todo o meu post, eu disse explicitamente que o código é bobo e sugeri exatamente o que você disse em seu comentário.
precisa saber é o seguinte
2
Desculpe, você está certo ... Esqueci que havia uma grande reestruturação de exceções no Python 2.5. Tentei desfazer o voto negativo, mas o SO só me permite fazer isso se a resposta for editada. Portanto, como estamos em 2012 e o Python 2.4 é uma história antiga, por que não editá-lo e mostrar o código (atual) correto antecipadamente, deixando o método anterior à 2.5 como nota de rodapé? Isso melhorará muito a resposta e poderei desfazer o voto negativo, e terei prazer em fazê-lo.
Vantajoso para as duas partes
@MestreLion: Comecei a editar como você sugeriu, mas essa resposta realmente só faz sentido no contexto da pergunta e no ambiente 2.4. O voto negativo não me chateia.
precisa saber é o seguinte
48
import sys
sys.exit(1)
Wojciech Bederski
fonte
9

algo parecido import sys; sys.exit(0)?

roubar
fonte
@mestreLion Então por que recebo Dets 06 18:53:17 Traceback (última chamada mais recente): Arquivo "debug_new.py", linha 4, em <module> import sys; sys.exit (0) SystemExit: 0 em org.python.core.PyException.fillInStackTrace (PyException.java:70) no meu console?
Val
3
@ Val: porque você não está usando um console python padrão. Jython não é Python e parece que (ou pelo menos seu console) lida com exceções de maneira diferente.
precisa saber é o seguinte
8

O código a seguir não gera uma exceção e sai sem um rastreamento:

import os
os._exit(1)

Consulte esta pergunta e respostas relacionadas para obter mais detalhes. Surpreso por que todas as outras respostas são tão complicadas demais.

IlliakaillI
fonte
4

É uma prática muito melhor evitar o uso de sys.exit () e, em vez disso, gerar / manipular exceções para permitir que o programa termine corretamente. Se você deseja desativar o traceback, basta usar:

sys.trackbacklimit=0

Você pode definir isso na parte superior do seu script para compactar toda a saída do traceback, mas eu prefiro usá-la com mais moderação, por exemplo, "erros conhecidos" onde eu quero que a saída fique limpa, por exemplo, no arquivo 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."

Se CalledProcessError for capturado, a saída será semelhante a esta:

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

Se ocorrer outro erro, ainda obteremos a saída completa do traceback.

RCross
fonte
1
Para usar sys.trackbacklimitno Python 3, consulte esta resposta .
Acumenus 06/10
4

Use a função python interna quit () e é isso. Não há necessidade de importar nenhuma biblioteca. Estou usando python 3.4

Miled Louis Rizk
fonte
2

Eu faria assim:

import sys

def do_my_stuff():
    pass

if __name__ == "__main__":
    try:
        do_my_stuff()
    except SystemExit, e:
        print(e)
Karl W.
fonte
0

A respeito

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

Sem rastreamento e de alguma forma mais explícita.

agcala
fonte
-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
Brian Zimmerman
fonte
7
Se você comentar o código, aumentará a qualidade da resposta.