python异常消息捕获


519
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))

这似乎不起作用,出现语法错误,将所有类型的异常记录到文件中的正确方法是什么


2
您的缩进已损坏。并省略,之后except
Sven Marnach

3
@SvenMarnach,如果省略,after except,则会得到global name 'e' is not defined,这并不比错误的语法好多少。
2013年

12
@Val:应为except Exception as eexcept Exception, e,具体取决于Python版本。
Sven Marnach 2013年

1
大概是在这8个答案附近,但是当您打开文件时,关闭部分永远都不应位于try语句内,而应位于finally语句中或由with语句包装。
罗卡蒙德

Answers:


732

您必须定义要捕获的异常类型。所以写except Exception, e:的,而不是except, e:一个普通的异常(即无论如何都会被记录)。

其他可能性是通过这种方式编写您的整个try / except代码:

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))

在Python 3.x和现代版本的Python 2.x中,使用except Exception as e代替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))

118
repr(e)给您例外(和消息字符串);str(e)仅给出消息字符串。
白胡子

11
作为记录异常的替代方法,您可以logger.exception(e)改用。它将在同一logging.ERROR级别记录具有追溯的异常。
mbdevpl

1
@mbdevpl这似乎不正确。似乎在以下情况下调用了str():ideone.com/OaCOpO
KevinOrr,2016年

6
except Exception, e:在python 3中向我抛出语法错误。这是预期的吗?
查理·帕克

27
@CharlieParker用Python3编写except Exception as e:
eumiro's

281

python 3不再支持该语法。请改用以下内容。

try:
    do_something()
except BaseException as e:
    logger.error('Failed to do something: ' + str(e))

2
实际上,您应该使用logger.error('做某事失败:%s',str(e))这样,如果您的记录器级别高于错误,则不会进行字符串插值。
avyfain

7
@avyfain-您不正确。该语句logging.error('foo %s', str(e))将始终转换e为字符串。要实现您的后遗症,可以使用logging.error('foo %s', e)-从而允许日志记录框架执行(或不执行)转换。
罗恩·达尔格伦

1
您可以在python REPL中进行验证(在此处使用Python 3.5.2和ipython):在这里查看我的要点
Ron Dahlgren

2
作为记录异常的替代方法,您可以logger.exception(e)改用。它将在同一logging.ERROR级别记录具有追溯的异常。
mbdevpl

11
要注意的是except BaseException,并except Exception没有在同一水平上。except Exception确实可以在Python3中工作,但是它不会捕获KeyboardInterrupt实例(如果您希望能够中断代码,这将非常方便!),但是BaseException捕获任何异常。有关异常的层次结构,请参见此链接
jeannej

41

将其更新为更简单的记录器(适用于python 2和3)。您不需要回溯模块。

import logging

logger = logging.Logger('catch_all')

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

现在这是旧方法(尽管仍然有效):

import sys, traceback

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

exc_value是错误消息。


2
这将是我的首选方法。我想只打印字符串对于日志记录很有用,但是如果我需要对该信息做任何事情,我不仅需要一个字符串。
sulimmesh '16

3
在第二个示例中,您不需要“导入回溯”,对吗?
starikoff

35

在某些情况下,您可以使用e.messagee.messages ..但是,并非在所有情况下都有效。无论如何,使用str(e)更安全

try:
  ...
except Exception as e:
  print(e.message)

42
这里的问题是,例如,如果你except Exception as ee是一个IOError,你e.errnoe.filenamee.strerror,但显然没有e.message(至少在Python 2.7.12)。如果要捕获错误消息,请使用str(e)和其他答案一样。
epalm '17

@epalm如果在异常之前捕获IOError怎么办?
艾伯特·汤普森

@HeribertoJuárez为什么可以捕获特殊情况,而又可以将其简单地转换为字符串?
HosseyNJF

25

如果您需要错误类,错误消息和堆栈跟踪(或其中一些),请使用sys.exec_info()

带有某些格式的最少工作代码:

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)

给出以下输出:

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

函数sys.exc_info()为您提供有关最新异常的详细信息。返回的元组(type, value, traceback)

traceback是回溯对象的实例。您可以使用提供的方法来格式化跟踪。在追溯文档中可以找到更多内容


3
使用e.__class__.__name__ 也可以返回异常类。
kenorb

19

您可以使用logger.exception("msg")traceback记录异常:

try:
    #your code
except Exception as e:
    logger.exception('Failed: ' + str(e))

巧合的e.msgExceptionclass 的字符串表示形式。
MarkHu

5
或者干脆logger.exception(e)
mbdevpl


5

您可以尝试明确指定BaseException类型。但是,这只会捕获BaseException的派生类。尽管这包括所有实现提供的异常,但也可能会引发任意旧式类。

try:
  do_something()
except BaseException, e:
  logger.error('Failed to do something: ' + str(e))


2

对于未来的奋斗者,在python 3.8.2(可能还有之前的几个版本)中,语法为

except Attribute as e:
    print(e)

1

使用str(e)repr(e)表示异常,您将无法获得实际的堆栈跟踪,因此查找异常在哪里没有帮助。

阅读其他答案和日志记录包doc之后,以下两种方法可以很好地打印实际的堆栈跟踪信息,以便于调试:

logger.debug()与参数一起使用exc_info

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

采用 logger.exception()

或者我们可以直接使用它logger.exception()来打印异常。

try:
    # my code
exception SomeError as e:
    logger.exception(e)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.