繁体   English   中英

Python 动态 inheritance 来自异常

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM