【问题标题】:Customizing exceptions in python? writing logs in custom exception class?在python中自定义异常?在自定义异常类中编写日志?
【发布时间】:2013-05-28 09:46:40
【问题描述】:

我正在我的 python 代码中自定义异常。我已将异常类继承到其他类,现在将一些自定义错误定义为从我的自定义异常类派生的类,如下所示:

class DataCollectorError(Exception): pass
class ParamNullError(DataCollectorError) : pass
class ParamInvalidTypeError(DataCollectorError) : pass

我在我的 python 函数中提出了这些异常,例如:

def READ_METER_DATA (regIndex, numRegisters, slaveUnit):
    try:
        if not regIndex:
            raise ParamNullError, "register index is null"

        if not numRegisters:
            raise ParamNullError, "number of registers should not be null"

        if not slaveUnit:
            raise ParamNullError, "Meter Id should not be null"

并记录错误,例如:

except DataCollectorError as d:
    lgr.error('DataCollector Error(READ_METER_DATA): '+d.args[0])
    print 'DataCollector Error:(READ_METER_DATA)', d.args[0]
except:
    lgr.error('Unexpected Error: ', sys.exc_info())
    print 'Unexpected Error: ', sys.exc_info()
    pass

但这违背了单元测试脚本的目的,因为它不会在我的单元测试脚本知道之前被我的 catch 块捕获是否引发异常。所以我想在基类本身中记录这些错误 -

Class ParamNullError(DataCollectorError):
    <----here----------->
    pass 

谁能告诉我如何获取引发异常时传递的字符串?

【问题讨论】:

  • 您不需要像以前那样为您的异常自定义日志记录;改用lgr.exception() 并让logging 模块自动处理异常(也无需调用sys.exc_info()。像您这样的自定义异常将在没有任何特殊大小写的情况下处理。

标签: python exception inheritance exception-handling custom-exceptions


【解决方案1】:

只需使用 __init____str__ 方法扩展您的错误类。

例子:

class DataCollectorError(Exception):
    def __init__(self, msg=''):
        self.msg = msg
        log(msg)  # use your logging things here

    def __str__(self):
        return self.msg

使用msg='',因为这样您就不需要总是指定消息。

【讨论】:

  • 如果我将我的异常引发部分从尝试中移出,是否有可能程序在检查任何 if 时失败,并且我将无法捕获它,因为它没有尝试.. 程序会在那里失败?因为我不希望它在没有任何日志的情况下失败
  • 我不知道我是否理解正确,但是使用我的代码(你必须用你的日志记录函数替换log)会引发异常,但在程序停止之前(如果你不't catch the exception)它会将消息写入日志(您在__init__中所做的一切都将在退出之前执行)。如果你想默默地忽略异常,你必须在 try ... except 块中加注
【解决方案2】:

不要。

分解出您需要进行单元测试的调用,并将您的异常处理程序移出:

try:
     testableFunctionCall()
except:
     lgr.exception('Unexpected Error')

并测试testableFunctionCall()

或者,使用testfixtures library 测试日志记录本身:

from testfixtures import LogCapture
with LogCapture() as l:
    callFunctionUnderTest()

l.check(
     ('packagename', 'ERROR', 'DataCollector Error(READ_METER_DATA): foobar'),
)

【讨论】:

  • 如果我将我的异常引发部分从尝试中移出,是否有可能程序在检查任何 if 时失败,并且我将无法捕获它,因为它没有尝试.. 程序会在那里失败?因为我不希望它在没有任何日志的情况下失败
  • @InderpalSingh:将功能移至函数不会改变引发异常时发生的情况。除非您在 new 位置调用该函数,否则该异常仍将被该处理程序捕获。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 2019-06-03
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多