I'm trying to create a custom Exception which can inherit from all the Exceptions. I've used a wrapper, here's my code:
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.
Suggestions?
This is a rather tricky problem. The issue is that the very creation of your specialized MyError fails with an IndexError
. Because an IndexError
is not a KeyError
, it passes right through the attempt to catch it and instead is caught as a 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
You should instead create your error like so:
raise _MyError(KeyError, 'hello')
Exceptions does not accept message
; causes super(MyError, self).__init__(self, *_args, **_kwargs)
fail.
>>> IndexError(message='asdf')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: exceptions.IndexError does not take keyword arguments
You need to convert message
to positional argument:
def _MyError(_type, *args, **kwargs):
class MyError(_type, object):
def __init__(self, message=None):
super(MyError, self).__init__(self, message)
return MyError(*args, **kwargs)
When I try your code in Python 2.7 I get the following error:
Traceback (most recent call last):
File "test.py", line 13, in <module>
except MyError as e:
NameError: name 'MyError' is not defined
This is not surprising, because the name MyError
does not exist at the file-level scope where you are trying to catch it.
Also consider that you're creating a new class each time you call the _MyError()
function. So even if there were a MyError
class available to use in the except
block, it would almost certainly be the wrong class (albeit with the same name).
I suspect you might want to create a "root" MyError
class, and then create a MyCustomError
class in your function. You could then catch the MyError
(base) class in your exception
block and proceed from there.
EDIT
Per your comment, you might be able to do something like this:
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)
I suggest you create a class factory to build your error type dynamically, as explained in the official docs .
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`
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.