Qual é a melhor maneira de obter mensagens de exceções de componentes da biblioteca padrão em Python?
Percebi que em alguns casos você pode obtê-lo por meio de um message
campo como este:
try:
pass
except Exception as ex:
print(ex.message)
mas em alguns casos (por exemplo, no caso de erros de soquete), você deve fazer algo assim:
try:
pass
except socket.error as ex:
print(ex)
Eu me perguntei se existe alguma maneira padrão de cobrir a maioria dessas situações.
python
exception
exception-handling
Coração congelado
fonte
fonte
except Foo as bar:
é o mesmo queexcept Foo, bar:
(exceto que a primeira é mais recente e continuará a funcionar na 3.x), independentemente de o erro vir com ummessage
atributo ou não é separado..message
por erro é o método padrão ou não?print(msg)
é apenas um atalho paraprint(str(msg))
message
está obsoleto.Respostas:
Se você olhar a documentação para os erros embutidos , verá que a maioria das
Exception
classes atribui seu primeiro argumento como ummessage
atributo. Porém, nem todos eles o fazem.Notavelmente,
EnvironmentError
(com subclassesIOError
eOSError
) tem um primeiro argumento deerrno
, segundo destrerror
. Não hámessage
...strerror
é aproximadamente análogo ao que normalmente seria ummessage
.De maneira mais geral, as subclasses de
Exception
podem fazer o que quiserem. Eles podem ou não ter ummessage
atributo. Os futurosException
s integrados podem não ter ummessage
atributo. QualquerException
subclasse importada de bibliotecas de terceiros ou código de usuário pode não ter ummessage
atributo.Acho que a maneira adequada de lidar com isso é identificar as
Exception
subclasses específicas que você deseja capturar e, em seguida, capturar apenas aquelas em vez de tudo com um eexcept Exception
, em seguida, utilizar quaisquer atributos que essa subclasse específica defina como você quiser.Se você precisar de
print
alguma coisa, acho que imprimir a captura emException
si provavelmente fará o que você quiser, tenhamessage
ou não um atributo.Você também pode verificar o atributo de mensagem se quiser, assim, mas eu não iria sugerir isso, pois parece confuso:
try: pass except Exception as e: # Just print(e) is cleaner and more likely what you want, # but if you insist on printing message specifically whenever possible... if hasattr(e, 'message'): print(e.message) else: print(e)
fonte
str(ex)
vez de apenasex
?print()
liga automaticamentestr()
para você. Não há razão para chamá-lo manualmente, embora seja inofensivo, já que chamarstr()
uma string retornará apenas a própria string.str()
se a mensagem for do tipounicode
.Para melhorar a resposta fornecida por @artofwarfare , aqui está o que considero uma maneira mais simples de verificar o
message
atributo e imprimi-lo ou imprimir oException
objeto como um fallback.try: pass except Exception as e: print getattr(e, 'message', repr(e))
A chamada para
repr
é opcional, mas acho que é necessária em alguns casos de uso.Atualização # 1:
Após o comentário de @MadPhysicist , aqui está uma prova de por que a chamada para
repr
pode ser necessária. Tente executar o seguinte código em seu interpretador:try: raise Exception except Exception as e: print(getattr(e, 'message', repr(e))) print(getattr(e, 'message', str(e)))
Atualização # 2:
Aqui está uma demonstração com especificações para Python 2.7 e 3.5: https://gist.github.com/takwas/3b7a6edddef783f2abddffda1439f533
fonte
getattr
lança uma exceção se o objeto passado não tiver o atributo solicitado. Se você queria fazer algo assim, eu acho que você deve usar o terceiro argumento opcional paragetattr
, como este:print getattr(e, 'message', e)
. Debativelmente melhor do que o que eu fiz. Outra opção seriaprint(e.message if hasattr(e, 'message') else e)
.str
vez derepr
.str
,repr
apenas adiciona o nome da classe. Em vez de usarrepr
, proponho usarprint('{e.__class__.__name__}: {e}'.format(e=e))
. A saída de impressão é mais limpa e adere à própria saída de aumento.'{e.__class__.__module__}.{e.__class__.__name__}: {e}'
repr(e)
por enquanto, foi a única solução que me ajudou a imprimir pelo menos uma quantidade mínima de informações sobre um erro que detectei em alguma circunstância específica.repr(e)
produzKeyError(0,)
(que é o erro), enquantostr(e)
oue.message
produziu apenas0
ou nada, respectivamente.Eu tive o mesmo problema. Acho que a melhor solução é usar log.exception, que imprimirá automaticamente o rastreamento de pilha e a mensagem de erro, como:
try: pass log.info('Success') except: log.exception('Failed')
fonte
log
? Acabei de experimentar oimport log
Python 2.7.13 e recebi uma mensagem de que não há nenhum módulo com esse nome. É algo que você adicionou por meio depip
ou foi adicionado em uma versão mais recente do python (eu sei, eu sei, eu preciso atualizar para o Python 3 ... farei isso assim que o CentOS parar de ser fornecido com o Python 2 por padrão ...)import logging
\ nlog = logging.getLogger(__name__)
Eu também tive o mesmo problema. Investigando isso, descobri que a classe Exception tem um
args
atributo, que captura os argumentos usados para criar a exceção. Se você restringir as exceções que, exceto serão capturadas, a um subconjunto, poderá determinar como elas foram construídas e, portanto, qual argumento contém a mensagem.try: # do something that may raise an AuthException except AuthException as ex: if ex.args[0] == "Authentication Timeout.": # handle timeout else: # generic handling
fonte