python - 向所有 python 异常添加额外信息

标签 python oop exception decorator

在又一次可怕的错误搜索之后,我想知道以下内容: 是否可以向所有异常添加一些额外信息,例如对象的名称。 这将大大提高错误的可读性,并更快地查找错误(或输入错误)。如果一个人有许多来自同一个类的对象,因此共享很多代码,但具有不同的属性,情况尤其如此。在这种情况下,如果错误消息还指出错误中对象的名称,这将非常有用。

一个简单的例子:我正在尝试模拟不同类型的设施,一个养 pig 场和一个奶牛场。它们是同一个类,但具有不同的属性。在模拟中进行了许多设施,如果引发异常,如果将对象的名称添加到异常中将非常有帮助。

class facility():
    def __init__(self, name):
        self.name = name
        self.animals = []

farms = []
farms.append(facility('cow_farm'))
farms.append(facility('pig_farm'))
print farms[0].stock

这会产生

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: facility instance has no attribute 'stock'

但我想添加设施的名称:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: facility instance has no attribute 'stock'
  Name of object: cow_farm

我试过类似的东西

def print_name(exception):
    try:
        print self.name
    except AttributeError:
        pass
    raise exception

@print_name
Exception

但这行不通。是否有可能做这样的事情,或者是否有充分的理由不这样做?

最佳答案

如果你想处理错误和添加信息,你可以这样做:

farm = farms[0]
try:
    print farm.stock
except AttributeError:
    raise AttributeError("{} has no attribute 'stock'".format(farm.name))

但是,在 __init__ 中添加空的 stock 以避免此错误可能更明智。

你应该 never use a bare except ,因为它对您隐藏了有用的信息(特别是在开发和调试时!)通常,每个 try block 应该尽可能短,最好只做一件事。如果多个错误可能源于单个 try block ,您可以添加多个处理程序:

try:
    print farm.stock["hay"]
except AttributeError:
    raise AttributeError("{} has no attribute 'stock'".format(farm.name))
except KeyError:
    raise KeyError("{} has no 'hay' in 'stock'".format(farm.name))

(尽管请注意,在 __init__ 中添加 self.stock 并检查 if "hay"in farm.stock: 会让你免于此错误处理。)

如果发生您未预料到的错误,通常最好将该错误向上传播到调用堆栈,直到它被显式处理或您看到它。否则,您将走向这种愚蠢的反模式:

def some_func(*args, **kwargs):
    try:
        # all of some_func's content goes here
    except:
        raise Exception("Something went wrong in some_func().")

这对您毫无用处,而且对于任何试图使用您的代码的人来说都非常令人沮丧。

如果你想在级别处理这样的AttributeError,你可以这样做:

class Facility(object):

    def __init__(self, ...):
        ...

    def __getattr__(self, key):
        """Called on attempt to access attribute instance.key."""
        if key not in self.__dict__:
            message = "{} instance '{}' has no attribute '{}'."
            message = message.format(type(self).__name__,
                                     self.name, key)
            raise AttributeError(message)
        else:
            return self.__dict__[key]

然后你会得到

>>> farm = Facility("pig farm")
>>> print farm.stock
...
"AttributeError: Facility instance 'pig farm' has no attribute 'stock'."

如果你想在多个类中使用这个模式,你可以创建一个父类(super class):

class ProtectedAttrs(object):

    def __init__(self, name):
        self.name = name

    def __getattr__(self, key):
        ...

class Facility(ProtectedAttrs):

    def __init__(self, name):
        super(Facility, self).__init__(name)
        self.animals = []

这种方法适用于某些类型的错误。但是,我不知道有任何通用方法可以通过引用所涉及的实例来处理所有 错误。

关于python - 向所有 python 异常添加额外信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20881403/

相关文章:

python - 使用 plt.imshow() 显示多张图片

python - 通过 cross_val 保存 sklearn 分类器拟合

oop - Scala mixin 真的比多重 C++ 继承更好吗?

java - 如何从 Java 引发 Jython 异常?

python - 在 Django 中为您的模板提供一个全局变量

python - 沿给定轴打乱 NumPy 数组

C++ 从 int* 到 int 的无效转换

java - 调用类的接口(interface)方法

java - 遍历列表,同时从列表中删除

python - Python 中响应全局对象的异常