Como você faz com que exceções não capturadas sejam exibidas através do logging
módulo, e não stderr
?
Sei que a melhor maneira de fazer isso seria:
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
Mas minha situação é tal que seria muito bom se logging.exception(...)
fosse invocada automaticamente sempre que uma exceção não fosse detectada.
python
logging
exception-handling
Jacob Marble
fonte
fonte
Respostas:
Como Ned apontou,
sys.excepthook
é invocado toda vez que uma exceção é levantada e não capturada. A implicação prática disso é que, no seu código, você pode substituir o comportamento padrão desys.excepthook
fazer o que quiser (incluindo o usologging.exception
).Como exemplo do homem de palha:
Substituir
sys.excepthook
:Cometa erro de sintaxe óbvio (deixe de fora os dois pontos) e recupere informações de erro personalizadas:
Para mais informações sobre
sys.excepthook
, leia os documentos .fonte
type
como argumento de função, embora os IDEs se queixem de ocultar o globaltype
(bem como usarvar self = this
Javascript). Realmente não importa, a menos que você precise acessar otype
objeto dentro de sua função; nesse caso, você pode usartype_
como argumento.sys.excepthook
NÃO é chamado quando uma exceção é "gerada". É chamado quando o programa termina devido a uma exceção não capturada, que não pode ocorrer mais de uma vez.Aqui está um pequeno exemplo completo que também inclui alguns outros truques:
Ignore KeyboardInterrupt para que um programa python do console possa sair com Ctrl + C.
Confie inteiramente no módulo de log do python para formatar a exceção.
Use um criador de logs personalizado com um manipulador de exemplo. Essa alteração altera a exceção não tratada para ir para stdout em vez de stderr, mas você pode adicionar todos os tipos de manipuladores nesse mesmo estilo ao objeto de logger.
fonte
logger.critical()
dentro do manipulador excepthook, já que uma exceção não capturada é bastante crítica, eu diria.logging.basicConfig(level=logging.DEBUG, filename="debug.log", format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
Mas não ajudou.O método
sys.excepthook
será chamado se uma exceção for detectada: http://docs.python.org/library/sys.html#sys.excepthookfonte
type
a instância?sys.excepthook
?Por que não:
Aqui está a saída com
sys.excepthook
como visto acima:Aqui está a saída com o
sys.excepthook
comentado:A única diferença é que o primeiro tem
ERROR:root:Unhandled exception:
no início da primeira linha.fonte
sys.stderr
.Para aproveitar a resposta de Jacinda, mas usando um objeto logger:
fonte
functools.partial()
vez de lambda. Veja: docs.python.org/2/library/functools.html#functools.partialAgrupe sua chamada de entrada do aplicativo em um
try...except
bloco para poder capturar e registrar (e talvez aumentar novamente) todas as exceções não capturadas. Por exemplo, em vez de:Faça isso:
fonte
Talvez você possa fazer algo na parte superior de um módulo que redireciona o stderr para um arquivo e depois registrá-lo na parte inferior
fonte
Embora a resposta de @ gnu_lorien tenha me dado um bom ponto de partida, meu programa falha na primeira exceção.
Eu vim com uma solução aprimorada personalizada (e / ou), que silenciosamente registra Exceções de funções decoradas
@handle_error
.fonte
Para responder à pergunta do Sr. Zeus discutida na seção de comentários da resposta aceita, eu uso isso para registrar exceções não capturadas em um console interativo (testado com o PyCharm 2018-2019). Eu descobri
sys.excepthook
que não funciona em um shell python, então eu olhei mais fundo e descobri que poderia usá-losys.exc_info
. No entanto,sys.exc_info
não há argumentos diferentes dossys.excepthook
três argumentos.Aqui, eu uso os dois
sys.excepthook
esys.exc_info
para registrar as exceções em um console interativo e um script com uma função de wrapper. Para anexar uma função de gancho a ambas as funções, tenho duas interfaces diferentes, dependendo se argumentos são fornecidos ou não.Aqui está o código:
A configuração do registro pode ser encontrada na resposta de gnu_lorien.
fonte
No meu caso (usando
python 3
) ao usar a resposta de @Jacinda, o conteúdo do traceback não foi impresso. Em vez disso, ele simplesmente imprime o objeto em si:<traceback object at 0x7f90299b7b90>
.Em vez disso, eu faço:
fonte