2011-08-09 199 views
18

我目前正在编写一个包装类。我希望能够正确记录异常,但允许调用方法知道发生的异常。我的阶级是这样的:Python日志记录异常

import logging 

log = logging.getLogger('module') 

class MyAPIWrapper(library.APIClass): 

    def __init__(self): 
     self.log = logging.getLogger('module.myapiwrapper') 


    def my_wrapper_method(self): 
     try: 
      response = self.call_api_method() 
      return response.someData 
     except APIException, e: 
      self.log.exception('Oh noes!') 
      raise e #Throw exception again so calling code knows it happened 

我有点半信半疑捕获和异常只是为了记录它,然后重新认识它,以便调用代码可以做什么。这里有什么合适的模式?

+0

[蟒异常记录](HTTP的可能重复:// stackoverflow.com/questions/5191830/python-exception-logging) – lpapp

+0

这正是我正在做的。感谢您发布这个问题。 – smwikipedia

回答

22

捕捉记录没有任何问题。不过,我建议:

try: 
     response = self.call_api_method() 
    except APIException, e: # or 'as e' depending on your Python version 
     self.log.exception('Oh noes!') 
     raise #Throw exception again so calling code knows it happened 
    else: 
     return response.someData 

通过只是做了裸raise您保留完整的追溯信息。如果你在else子句中没有例外,那么只会发生这样的代码,并且它更清楚地表明你从哪一行中捕获异常。

对于调用类来说,如果它正在处理错误,那么也可以进行日志记录,但这对您的应用程序可能并不方便。

编辑:try ... except ... else ... finally的文档在compound statements之下。

+0

最后一个关键字应该是“except”而不是“else”还是用于某种目的? – jlafay

+4

它应该是'else'。 else子句只有在没有异常时才会发生,就像'for'和'while'循环上的'else'子句只有在没有'break'时才会发生。 – agf

+0

太棒了!感谢您的解释。 – jlafay

6

该方法是正确的,但不应该使用raise e,而应该使用raise,它会自动重新提升最后一个异常。这也是使用毯子except被认为可以接受的罕见情况之一。

这里很相似,你是从Python文档上做Handling Exceptions什么一个例子:

最后一个except子句可以省略例外姓名(或名称),以作为通配符。请谨慎使用此功能,因为以这种方式很容易掩盖真正的编程错误!它也可以被用于打印的错误信息,然后重新抛出异常(允许呼叫者来处理异常以及):

import sys 

try: 
    f = open('myfile.txt') 
    s = f.readline() 
    i = int(s.strip()) 
except IOError as (errno, strerror): 
    print "I/O error({0}): {1}".format(errno, strerror) 
except ValueError: 
    print "Could not convert data to an integer." 
except: 
    print "Unexpected error:", sys.exc_info()[0] 
    raise