[英]Python dynamic inheritance from Exceptions
我正在尝试创建一个可以从所有异常继承的自定义异常。 我使用了包装器,这是我的代码:
def _MyError(_type, message=None, *args, **kwargs):
class MyError(_type, object):
def __init__(self, *_args, **_kwargs):
super(MyError, self).__init__(self, message, *_args, **_kwargs)
return
return MyError(*args, **kwargs)
if(__name__ == '__main__'):
try:
raise _MyError(KeyError, message="ooops")
except MyError as e:
print "MyError occurred. ", e.message
except BaseException:
print "MyError not recognized.\n"
try:
raise _MyError(IndexError, message="ooops")
except IndexError as e:
print "MyError occurred. ", e.message
except BaseException:
print "MyError not recognized.\n"
exit
Output:
MyError not recognized.
MyError not recognized.
建议?
这是一个相当棘手的问题。 问题是您的专用 MyError 的创建失败并显示IndexError
。 因为IndexError
不是KeyError
,它直接通过尝试捕获它,而是作为BaseException
。
def _MyError(_type, *args, **kwargs):
class MyError(_type, object):
def __init__(self, *_args, **_kwargs):
super(MyError, self).__init__(self, *_args, **_kwargs)
# Error on above line (IndexError from kwargs not accepted)
return MyError(*args, **kwargs) # Error goes through here
try:
raise _MyError(KeyError, message='hello')
# raise never gets invoked, IndexError on calling _MyError
except KeyError: # IndexError != KeyError. This clause is skipped
print 'KeyError'
# except BaseException:
# print 'BaseException'
# Commenting out the above lines will throw the error instead of catching it
你应该像这样创建你的错误:
raise _MyError(KeyError, 'hello')
异常不接受message
; 导致super(MyError, self).__init__(self, *_args, **_kwargs)
失败。
>>> IndexError(message='asdf')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: exceptions.IndexError does not take keyword arguments
您需要将message
转换为位置参数:
def _MyError(_type, *args, **kwargs):
class MyError(_type, object):
def __init__(self, message=None):
super(MyError, self).__init__(self, message)
return MyError(*args, **kwargs)
当我在 Python 2.7 中尝试您的代码时,出现以下错误:
Traceback (most recent call last):
File "test.py", line 13, in <module>
except MyError as e:
NameError: name 'MyError' is not defined
这并不奇怪,因为名称MyError
在您尝试捕获它的文件级范围内不存在。
还要考虑到每次调用_MyError()
函数时都在创建一个新类。 因此,即使有一个MyError
可用类的使用except
块,它几乎肯定是错误的类(虽然名称相同)。
我怀疑您可能想要创建一个“根” MyError
类,然后在您的函数中创建一个MyCustomError
类。 然后,您可以在exception
块中捕获MyError
(基)类并从那里继续。
编辑
根据您的评论,您可能可以执行以下操作:
class MyError:
"""Marker class for mixin."""
pass
def my_error(_type, message=None, *args, **kwargs):
class _MySubclass(_type, MyError):
def __init__(self, *_args, **_kwargs):
super(_MySubclass, self).__init__(message, *_args, **_kwargs)
return _MySubclass(*args, **kwargs)
try:
raise my_error(KeyError, message="key error")
except MyError as e:
print "MyError occurred: ", e.message
except BaseException:
print "Unknown error:", str(e)
try:
raise my_error(IndexError, message="index error")
except MyError as e:
print "MyError occurred: ", e.message
except BaseException:
print "Unknown error:", str(e)
我建议您创建一个 class 工厂来动态构建您的错误类型,如官方文档中所述。
def error_factory(name, *base_errors):
"""Dynamically create custom Error class."""
assert all(issubclass(e, Exception) for e in base_errors)
return type(name, base_errors, {})
try:
something()
except KeyError:
MyError = error_factory("MyError", KeyError)
raise MyError("A problem occured!") # this error is also a `KeyError`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.