Aumente o aviso no Python sem interromper o programa

189

Eu estou tentando gerar um aviso em Python sem fazer o programa travar / parar / interromper.

Eu uso a seguinte função simples para verificar se o usuário passou um número diferente de zero para ele. Nesse caso, o programa deve avisá-los, mas continue conforme o normal. Ele deve funcionar como o código abaixo, mas deve usar a classe ou Warning(), em vez de imprimir o aviso manualmente.Error()Exception()

def is_zero(i):
   if i != 0:
     print "OK"
   else:
     print "WARNING: the input is 0!"
   return i

Se eu usar o código abaixo e passar 0 para a função, o programa trava e o valor nunca é retornado. Em vez disso, quero que o programa continue normalmente e apenas informe ao usuário que ele passou 0 para a função.

def is_zero(i):
   if i != 0:
     print "OK"
   else:
     raise Warning("the input is 0!")
   return i

Quero poder testar se um aviso foi lançado testando-o por unittest. Se eu simplesmente imprimir a mensagem, não poderei testá-la com assertRaises em um ponto.

Tomas Novotny
fonte
Como exatamente você deseja notificar o usuário? por email ou SMS? causa que pode ser conectada, mas você precisa ser específico.
Jun
2
Por que você não apenas printa mensagem?
sje397
1
@ sje397 O ponto é que eu quero poder testar se um aviso foi lançado testando-o pela unittest. Se eu simplesmente imprimir a mensagem, não poderei fazer isso com assertRaises em um ponto.
Tomas Novotny

Respostas:

157

Você não deveria raiseavisar, deveria estar usando o warningsmódulo. Ao aumentá-lo, você está gerando erro, em vez de aviso.

SilentGhost
fonte
1
Muito obrigado. E como testo se o Aviso foi lançado usando o mais unittest? Não posso mais usar assertRaises ().
Tomas Novotny
@ Tomas Novotny, você pode capturar stdout e stderr e verifique se as strings emitidas pelo seu aviso estão localizadas dentro.
wheaties
15
@ Tomas: Eu nunca ouvi falar do desejo de testar avisos, mas existe um warnings.catch_warningsgerenciador de contexto que permitirá que você faça isso.
SilentGhost
290
import warnings
warnings.warn("Warning...........Message")

Veja a documentação do python: aqui

necromante
fonte
6
E warnings.warn("blabla", DeprecationWarning)por adicionar uma classe ao tipo de aviso que está sendo emitido
shadi 30/12/19
52

Por padrão, diferente de uma exceção, um aviso não interrompe.

Depois import warnings, é possível especificar uma classe Warnings ao gerar um aviso. Se um não for especificado, é literalmente UserWarningpor padrão.

>>> warnings.warn('This is a default warning.')
<string>:1: UserWarning: This is a default warning.

Para simplesmente usar uma classe preexistente, por exemplo DeprecationWarning:

>>> warnings.warn('This is a particular warning.', DeprecationWarning)
<string>:1: DeprecationWarning: This is a particular warning.

Criar uma classe de aviso customizada é semelhante a criar uma classe de exceção customizada:

>>> class MyCustomWarning(UserWarning):
...     pass
... 
... warnings.warn('This is my custom warning.', MyCustomWarning)

<string>:1: MyCustomWarning: This is my custom warning.

Para testar, considere assertWarnsou assertWarnsRegex.


Como alternativa, especialmente para aplicativos independentes, considere o loggingmódulo. Ele pode registrar mensagens com um nível de depuração , informações , aviso , erro , etc. mensagens Entrar com um nível de aviso ou superior são, por padrão, impressas no stderr.

Acumenus
fonte