Levantar exceções não tratadas em um segmento no segmento principal? [duplicado]
-
13-09-2019 - |
Pergunta
Esta questão já tem uma resposta aqui:
Existem algumas perguntas semelhantes, mas nenhum fornecer a resposta que necessita.
Se eu criar tópicos via threading.Thread
, que, em seguida, lançar exceções que são sem tratamento, esses segmentos são terminados. Eu gostaria de manter o padrão imprimir os detalhes de exceção com o rastreamento de pilha, mas derrubar todo o processo também.
Eu considerei que poderia ser possível capturar todas as exceções nos tópicos e reraise-los no objeto thread principal, ou talvez seja possível realizar manualmente o tratamento de exceção padrão e, em seguida, levantar uma SystemExit
no segmento principal .
Qual é a melhor maneira de ir sobre isso?
Solução
Eu escrevi sobre Re-lançar exceções em Python , incluindo algo muito parecido isso como um exemplo.
Em seu segmento de trabalho você fazer isso (Python 2.x, veja abaixo para Python versão 3.x):
try:
self.result = self.do_something_dangerous()
except Exception, e:
import sys
self.exc_info = sys.exc_info()
e em seu segmento principal de fazer isso:
if self.exc_info:
raise self.exc_info[1], None, self.exc_info[2]
return self.result
A exceção será exibido no segmento principal apenas como se tivesse sido levantada no segmento de trabalho.
Python 3.x:
try:
self.result = self.do_something_dangerous()
except Exception as e:
import sys
self.exc_info = sys.exc_info()
e em seu segmento principal:
if self.exc_info:
raise self.exc_info[1].with_traceback(self.exc_info[2])
return self.result
Outras dicas
A única exceção um thread secundário pode aumentar de forma confiável no segmento principal é KeyboardInterrupt
: a forma como o thread secundário faz isso é chamando a função thread.interrupt_main()
. Não há nenhuma maneira de associar informações adicionais (sobre o motivo da exceção) com o objeto de exceção que começa levantado - o último está sempre apenas um KeyboardInterrupt
simples. Então, você precisa para esconder essa informação afastado em outro lugar, por exemplo, em uma instância dedicada do Queue.Queue - essa informação pode incluir os resultados do thread secundário pode obter via sys.exc_info()
, e qualquer outra coisa que você achar útil, claro.
O segmento principal será necessário para recuperar essa informação adicional (e ter em conta que a fila estará vazia se a interrupção do teclado é realmente devido ao usuário bater similares, assim, get_nowait
uso control-C ou e estar pronto para lidar com uma exceção Queue.Empty
, por exemplo), formate-o no entanto que você deseja, e terminar (se os tópicos secundários são daemon s, todo o processo termina quando os principais termina de rosca).
Muito infelizmente, a resposta aceita não responder à pergunta. Você prefere canalizar os detalhes da exceção em uma fila. Por favor, dê uma olhada em: pegar exceção de um segmento no segmento chamador em Python