[英]Add extra information to all python exceptions
After another terrible bug hunt, I am wondering the following: Is it possible to add some extra information to all exceptions, for example the name of an object. 在又一次可怕的bug搜索之后,我想知道以下内容:是否可以为所有异常添加一些额外信息,例如对象的名称。 This would increase the readability of the errors a lot and make looking for bugs (or input errors) a lot quicker.
这会大大增加错误的可读性,并且可以更快地查找错误(或输入错误)。 This is especially the case if one has many objects which are from the same class and therefore share much code, but have different attributes.
如果有多个对象来自同一个类并因此共享很多代码但具有不同的属性,则尤其如此。 In this case it can be very useful if the error message also states the name of the object in the error.
在这种情况下,如果错误消息还指出错误中对象的名称,则它非常有用。
A simplfied example: I am trying to simulate different types of facilities, a pig farm and a cow farm. 一个简单的例子:我正在尝试模拟不同类型的设施,养猪场和奶牛场。 These are the same class, but do have different attributes.
这些是同一个类,但确实有不同的属性。 In the simulation many facilities are made and if an exception is raised, it would be very helpful if the name of the object is added to the exception.
在模拟中,会创建许多工具,如果引发异常,如果将对象的名称添加到异常中将非常有用。
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
This would yield 这会产生
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: facility instance has no attribute 'stock'
But I would like to add the name of the facility: 但我想添加设施的名称:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: facility instance has no attribute 'stock'
Name of object: cow_farm
I tried something like 我试过类似的东西
def print_name(exception):
try:
print self.name
except AttributeError:
pass
raise exception
@print_name
Exception
But that doesn't work. 但这不起作用。 Is it possible to do such a thing, or are there good reasons not to do this?
有可能做这样的事情,还是有充分的理由不这样做?
If you want to handle errors and add information, you could do it as follows: 如果要处理错误并添加信息,可以按如下方式执行:
farm = farms[0]
try:
print farm.stock
except AttributeError:
raise AttributeError("{} has no attribute 'stock'".format(farm.name))
However, it might be wiser to add the empty stock
in __init__
to avoid this error. 但是,在
__init__
添加空stock
以避免此错误可能更明智。
You should never use a bare except
, as it hides useful information from you ( particularly when developing and debugging!) Generally, each try
block should be as short as possible, preferably doing only one thing. 你应该永远不会使用裸
except
,因为它隐藏你有用的信息( 尤其是发展中国家时,调试!)一般情况下,每一个try
块应该越短越好,最好做的只有一件事。 If multiple errors could stem from a single try
block, you can add multiple handlers: 如果多个错误可能来自单个
try
块,则可以添加多个处理程序:
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))
(Although note that adding self.stock
in __init__
and checking if "hay" in farm.stock:
would save you from this error handling.) (虽然请注意在
__init__
中添加self.stock
并检查self.stock
中的if "hay" in farm.stock:
会使您免于此错误处理。)
If an error happens that you weren't expecting, it is generally best for that error to propagate up the call stack until it is explicitly handled or you get to see it. 如果发生了您不期望的错误,通常最好将该错误传播到调用堆栈,直到它被明确处理或您看到它。 Otherwise, you are heading for this foolish anti-pattern:
否则,你正在走向这个愚蠢的反模式:
def some_func(*args, **kwargs):
try:
# all of some_func's content goes here
except:
raise Exception("Something went wrong in some_func().")
Which is no use to you and extremely frustrating for anyone trying to use your code. 这对你没用,对于任何试图使用你的代码的人来说都是非常令人沮丧的。
If you want to handle AttributeError
s like this at the class
level, you could do: 如果你想在
class
级别处理类似这样的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]
Then you will get 然后你会得到
>>> farm = Facility("pig farm")
>>> print farm.stock
...
"AttributeError: Facility instance 'pig farm' has no attribute 'stock'."
If you want to use this pattern with multiple classes, you can make a superclass: 如果要将此模式与多个类一起使用,可以创建一个超类:
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 = []
This sort of thing will work for some types of error. 这种事情适用于某些类型的错误。 However, I am not aware of any general way to handle all errors with references to the instance involved.
但是,我不知道通过引用所涉及的实例来处理所有错误的任何一般方法。
Most of exceptions contain message attribute, that give you additional information about error 大多数异常都包含message属性,可以为您提供有关错误的其他信息
In [163]: try:
.....: farm = []
.....: farm.stock
.....: except AttributeError as err:
.....: print err.message
.....:
'list' object has no attribute 'stock'
Exception traceback points you to a code line, so usually it is not hard to figure out the problem 异常回溯将您指向代码行,因此通常不难发现问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.