captura de mensagem de exceção python

520
import ftplib
import urllib2
import os
import logging
logger = logging.getLogger('ftpuploader')
hdlr = logging.FileHandler('ftplog.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
FTPADDR = "some ftp address"

def upload_to_ftp(con, filepath):
    try:
        f = open(filepath,'rb')                # file to send
        con.storbinary('STOR '+ filepath, f)         # Send the file
        f.close()                                # Close file and FTP
        logger.info('File successfully uploaded to '+ FTPADDR)
    except, e:
        logger.error('Failed to upload to ftp: '+ str(e))

Isso não parece funcionar, recebo erro de sintaxe, qual é a maneira correta de fazer isso para registrar todos os tipos de exceções em um arquivo

Hellnar
fonte
2
Seu recuo está quebrado. E omita o ,depois except.
Sven Marnach
3
@SvenMarnach, se você omitir o ,depois except, receberá global name 'e' is not defined, o que não é muito melhor do que a sintaxe errada.
Val
12
@ Val: deve ser except Exception as eou except Exception, e, dependendo da versão do Python.
Sven Marnach
1
Provavelmente está em torno dessas 8 respostas, mas quando você abre um arquivo, a parte fechada nunca deve estar dentro da instrução try, mas em uma declaração finalmente ou envolvida por uma declaração with.
JC Rocamonde

Respostas:

733

Você precisa definir qual tipo de exceção deseja capturar. Portanto, escreva em except Exception, e:vez de except, e:para uma exceção geral (que será registrada de qualquer maneira).

Outra possibilidade é escrever toda a sua tentativa / exceto código desta maneira:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception, e: # work on python 2.x
    logger.error('Failed to upload to ftp: '+ str(e))

no Python 3.xe versões modernas do Python 2.x, use em except Exception as evez de except Exception, e:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception as e: # work on python 3.x
    logger.error('Failed to upload to ftp: '+ str(e))
eumiro
fonte
118
repr (e) fornece a exceção (e a sequência de mensagens); str (e) fornece apenas a sequência de mensagens.
Barba branca
11
Como alternativa para a exceção de log, você pode usar logger.exception(e). Ele registrará a exceção com rastreamento no mesmo logging.ERRORnível.
precisa saber é o seguinte
1
@mbdevpl isso não parece ser verdade. Parece chamar str () sobre a exceção: ideone.com/OaCOpO
KevinOrr
6
except Exception, e:lança um erro de sintaxe para mim no python 3. Isso é esperado?
Charlie Parker
27
@CharlieParker no Python3 writeexcept Exception as e:
eumiro 1/17
282

A sintaxe não é mais suportada no python 3. Use o seguinte.

try:
    do_something()
except BaseException as e:
    logger.error('Failed to do something: ' + str(e))
sjtaheri
fonte
2
Na verdade, você deve usar logger.error ('Falha ao fazer algo:% s', str (e)) Dessa forma, se o nível do seu logger estiver acima do erro, ele não fará a interpolação de string.
Avyfain
7
@avyfain - Você está incorreto. A instrução logging.error('foo %s', str(e))sempre será convertida eem uma sequência. Para alcançar o que você está procurando, você usaria logging.error('foo %s', e)- permitindo assim que a estrutura de log fizesse (ou não) a conversão.
Ron Dahlgren 11/07
1
Você pode verificar em um python REPL (aqui com Python 3.5.2 e ipython): veja minha essência aqui
Ron Dahlgren
2
Como alternativa para a exceção de log, você pode usar logger.exception(e). Ele registrará a exceção com rastreamento no mesmo logging.ERRORnível.
precisa saber é o seguinte
11
Cuidado com isso except BaseExceptione except Exceptionnão está no mesmo nível. except Exceptionfunciona em Python3, mas não será capturado, KeyboardInterruptpor exemplo (o que pode ser muito conveniente se você quiser interromper seu código!), enquanto BaseExceptioncaptura qualquer exceção. Veja este link para a hierarquia de exceções.
jeannej
41

Atualizando isso para algo mais simples para o logger (funciona para python 2 e 3). Você não precisa do módulo traceback.

import logging

logger = logging.Logger('catch_all')

def catchEverythingInLog():
    try:
        ... do something ...
    except Exception as e:
        logger.error(e, exc_info=True)
        ... exception handling ...

Esta é agora a maneira antiga (embora ainda funcione):

import sys, traceback

def catchEverything():
    try:
        ... some operation(s) ...
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        ... exception handling ...

exc_value é a mensagem de erro.

Berniey
fonte
2
Este seria o meu método preferido. Apenas imprimir a sequência é útil para o registro, suponho, mas se precisar fazer alguma coisa com essas informações, preciso mais do que apenas uma sequência.
sulimmesh 30/03/16
3
Você não precisa 'importar traceback' no segundo exemplo, certo?
111318 Starikoff
34

Existem alguns casos em que você pode usar o e.message ou e.messages .. Mas ele não funciona em todos os casos. De qualquer forma, o mais seguro é usar o str (e)

try:
  ...
except Exception as e:
  print(e.message)
Slipstream
fonte
42
O problema com isto é, por exemplo, se você except Exception as e, e eé um IOError, você começa e.errno, e.filenamee e.strerror, mas aparentemente não e.message(pelo menos em Python 2.7.12). Se você deseja capturar a mensagem de erro, use str(e), como nas outras respostas.
Epalm 19/04
@epalm E se você pegar o IOError antes da exceção?
Albert Thompson
@ HeribertoJuárez Por que capturar casos especiais enquanto você pode simplesmente lançá-los em cordas?
HosseyNJF 19/04
25

Se você deseja a classe de erro, a mensagem de erro e o rastreamento de pilha (ou alguns deles), use sys.exec_info().

Código de trabalho mínimo com alguma formatação:

import sys
import traceback

try:
    ans = 1/0
except BaseException as ex:
    # Get current system exception
    ex_type, ex_value, ex_traceback = sys.exc_info()

    # Extract unformatter stack traces as tuples
    trace_back = traceback.extract_tb(ex_traceback)

    # Format stacktrace
    stack_trace = list()

    for trace in trace_back:
        stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))

    print("Exception type : %s " % ex_type.__name__)
    print("Exception message : %s" %ex_value)
    print("Stack trace : %s" %stack_trace)

O que fornece a seguinte saída:

Exception type : ZeroDivisionError
Exception message : division by zero
Stack trace : ['File : .\\test.py , Line : 5, Func.Name : <module>, Message : ans = 1/0']

A função sys.exc_info () fornece detalhes sobre a exceção mais recente. Retorna uma tupla de (type, value, traceback).

tracebacké uma instância do objeto traceback. Você pode formatar o rastreio com os métodos fornecidos. Mais informações podem ser encontradas na documentação do traceback .

Kavindu Dodanduwa
fonte
3
O uso também e.__class__.__name__ pode retornar a classe de exceção.
kenorb
19

Você pode usar logger.exception("msg")para registrar a exceção com o traceback:

try:
    #your code
except Exception as e:
    logger.exception('Failed: ' + str(e))
Pedro
fonte
Coincidentemente, e.msgé a representação de string da Exceptionclasse.
precisa saber é
5
Ou simplesmente logger.exception(e).
precisa saber é o seguinte
5

Você pode tentar especificar o tipo BaseException explicitamente. No entanto, isso capturará apenas derivados de BaseException. Embora isso inclua todas as exceções fornecidas pela implementação, também é possível gerar classes arbitrárias de estilo antigo.

try:
  do_something()
except BaseException, e:
  logger.error('Failed to do something: ' + str(e))
Heini Høgnason
fonte
4

Use str (ex) para imprimir a execução

try:
   #your code
except ex:
   print(str(ex))
Niraj Trivedi
fonte
2

para os futuros lutadores, no python 3.8.2 (e talvez algumas versões antes disso), a sintaxe é

except Attribute as e:
    print(e)
syter
fonte
1

Usando str(e)ou repr(e)para representar a exceção, você não receberá o rastreamento de pilha real, portanto, não é útil descobrir onde está a exceção.

Depois de ler outras respostas e o documento do pacote de log, as duas maneiras a seguir funcionam muito bem para imprimir o rastreamento de pilha real para facilitar a depuração:

use logger.debug()com parâmetroexc_info

try:
    # my code
exception SomeError as e:
    logger.debug(e, exc_info=True)

usar logger.exception()

ou podemos usar diretamente logger.exception()para imprimir a exceção.

try:
    # my code
exception SomeError as e:
    logger.exception(e)
jdhao
fonte