Existe uma maneira para evitar uma exceção SystemExit levantada a partir de sys.exit () de ser pego?

StackOverflow https://stackoverflow.com/questions/173278

Pergunta

Os documentos dizem que sys.exit de chamada () gera uma exceção SystemExit que pode ser pego em níveis exteriores. Eu tenho uma situação em que eu quero saída definitiva e, sem dúvida, de dentro de um caso de teste, no entanto, o unittest capturas módulo SystemExit e impede a saída. Isso normalmente é grande, mas a situação específica Eu estou tentando alça é aquele em que o nosso framework de teste detectou que ele está configurado para apontar para um banco de dados não-teste. Neste caso, eu quero sair e evitar novos testes sejam executados. É claro desde unittest armadilhas do SystemExit e continua alegremente sobre a sua maneira, ele está me frustrando.

A única opção que tenho pensado até agora está usando ctypes ou algo semelhante a saída chamada (3) diretamente, mas esta parece ser uma muito fugly cortar por algo que deve ser realmente simples.

Foi útil?

Solução

Você pode chamar os._exit() para sair diretamente, sem lançar uma exceção :

import os
os._exit(1)

Isso ignora toda a lógica de desligamento python, como o módulo atexit, e não será executado através da manipulação de exceção lógica que você está tentando evitar nesta situação. O argumento é o código de saída que será devolvido pelo processo.

Outras dicas

Como Jerub disse, os._exit(1) é sua resposta. Mas, considerando que ignora todas procedimentos de limpeza, incluindo blocos finally:, fechamento de arquivos, etc, e realmente deve ser evitado a todo o custo, I pode apresentar uma forma mais "seguro-ish" de usá-lo?

Se você problema é SystemExit ser pego em níveis exteriores (ie, unittest), então ser a nível externo a si mesmo! Envolva seu código principal em um try / exceto bloco , SystemExit captura, e chamada os._exit lá, e única lá! Desta forma, você pode chamar sys.exit normalmente em qualquer lugar do código, deixá-lo borbulhar para o nível superior, graciosamente fechar todos os arquivos e executar todas as limpezas, e então chamando os._exit.

Você pode até escolher quais saídas são os de "emergência". O código abaixo é um exemplo de tal abordagem:

import sys, os

EMERGENCY = 255  # can be any number actually

try:
    # wrap your whole code here ...
    # ... some code
    if x: sys.exit()
    # ... some more code
    if y: sys.exit(EMERGENCY)  # use only for emergency exits
    # ...
except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it
    else:
        os._exit(EMERGENCY)  # try to stop *that*, sucker!
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top