What does the following class does:
class HException(Exception):
def __init__(self, value=''):
self.value = value
def __str__(self):
return self.value
I saw it being called by raise
This is custom exception for more precise designations problems.
Not just an abstract exception. But an exception has arisen in a particular subject area.
class MoneyTransactionException(Exception):
...
says that something wrong with money manipulate in program.
User defined exceptions
Related
Im having some trouble with designing the exception classes for a Python web API. What I would like to do is have various exceptions set up with some default error codes/messages, but also allow the flexibility of creating a custom one.
Take the following code:
class APIException(Exception):
def __init__(self):
super().__init__(self.message)
#property
def message(self) -> str:
raise NotImplementedError
#property
def code(self) -> int:
raise NotImplementedError
#property
def response(self):
return {"error": self.message}, self.code
class UnknownException(APIException):
message = "An unknown error occurred."
code = 500
class UnauthorizedException(APIException):
message = "Unauthorized"
code = 401
This allows me to do things like raise UnauthorizedException, which work fine.
However, what I would like to be able to do is to raise arbitrary API exceptions, like raise APIException("This is a custom error", 404). Raising a set exception with arguments and raising an APIException without arguments do not need to be supported; I will not be raising them like that.
It doesn't seem I can do this cleanly with the way I have designed the inheritance above. I have tried other various approaches but none seem to be as clean as the example above.
What would be the best way to go about doing this sort of thing?
Have your APIException constructor take arguments, and have the subclasses implement constructors that provide those arguments:
class APIException(Exception):
def __init__(self, message, code):
super().__init__(message)
self.message = message
self.code = code
#property
def response(self):
return {"error": self.message}, self.code
class UnknownException(APIException):
def __init__():
super().__init__("An unknown error occurred.", 500)
class UnauthorizedException(APIException):
def __init__():
super().__init__("Unauthorized", 401)
I'm looking for a way to annotate return type of a factory function.
It returns random child of 'AlgorithmBase'.
class AlgorithmFactory:
_algorithm_types = AlgorithmBase.__subclasses__()
def select_random_algorithm(self) -> AlgorithmBase:
# Select random algorithm
algorithm_class = self._random_generator.choice(AlgorithmFactory._algorithm_types)
algorithm = algorithm_class()
return algorithm
I get error from mypy:
The error I'm getting is:
Cannot instantiate abstract class 'AlgorithmBase' with abstract attributes 'get_constraints' and 'satisfy_constraints'
There is no way to instantiate class 'AlgorithmBase' in this code, how to make mypy understand it?
I want to avoid specifying actual sub-classes with 'Union' in return type. Any suggestions?
The problem here wasn't return type, but '_algorithm_types'. mypy has no way to understand what type it is, so it assumed that it is like return type and got error.
The following code fix the issue:
_algorithm_types: List[Type[AlgorithmBase]] = AlgorithmBase.__subclasses__()
As far as I can tell this should work, but it seems like one or more of your AlgorithmBase subclasses doesn't implement these two abstract methods.
Running MyPy for
import abc
class AlgorithmBase(abc.ABC):
#abc.abstractmethod
def get_constraints(self):
raise NotImplementedError
#abc.abstractmethod
def satisfy_constraints(self):
raise NotImplementedError
class SomeAlgorithm(AlgorithmBase):
pass
class AlgorithmFactory:
def get(self) -> AlgorithmBase:
algorithm = SomeAlgorithm()
return algorithm
yields the same error you get, and it runs without any error once the methods are implemented.
import abc
class AlgorithmBase(abc.ABC):
#abc.abstractmethod
def get_constraints(self):
raise NotImplementedError
#abc.abstractmethod
def satisfy_constraints(self):
raise NotImplementedError
class SomeAlgorithm(AlgorithmBase):
def get_constraints(self):
pass
def satisfy_constraints(self):
pass
class AlgorithmFactory:
def get(self) -> AlgorithmBase:
algorithm = SomeAlgorithm()
return algorithm
How can I write a mixin, which raises an Exception if the class which is using this specific mixin is not created properly.
If I do these checks and balances in the __init__ or __new__ methods of the mixin, Exception is raised when this erroneous class tries to create an instance. Which is late, ideally the exception needs to be thrown when the compiler detects a wrong class. (Assuming, how to detect if a class is acceptable or not is a trivial matter)
To Illustrate the question
class ASampleMixin:
"""
A sample docstring
"""
def a_method(self):
raise NotImplementedError
def class_rule(self):
if something is wrong:
return False
return True
# more methods
class AClass(ASampleMixin, BaseClass):
"""
This class should satisfy a condition specified in class_rule method of the mixin
"""
# some methods
I am right now performing the check in the init method of mixin. Which raises an exception if rule returns False. Now this needs to be done at the time AClass is read by interpreter and not when I try to create an instance of AClass.
Is it possible even in dynamically typed languages like Python 3.5?
This sounds as if you want to create a custom metaclass that performs the check upon creation of the class object. See the documentation for metaclasses.
A metaclass example as reference:
class CustomType(type):
def __call__(cls, *args, **kwargs):
if not CustomType.some_rule(kwargs.pop('some_attr', None)):
raise Exception('Abort! Abort!')
return super(CustomType, cls).__call__(*args, **kwargs)
#staticmethod
def some_rule(var):
if type(var) is not str:
return False
return True
class A(object):
__metaclass__ = CustomType
class B(A):
pass
b = B(some_attr='f') # all is well
b = B() # raises
Say we have two classes, Class A with a custom error which is thrown frequently and it is part of its functionality.
#a.py
class AError(Exception):
"""This exception flags a functional error"""
pass
class A(object):
def work(self):
"""Throws AError when it is tired"""
raise AError() #This exception is raised eventually, business code removed for clarity
Class B, which uses class A to perform some operations.
#b.py
import a
class B(object):
def make_him_work(self, afected):
try:
afected.work()
except a.AError:
pass #This was expected, here will go some business logic
This works great, but it becomes an issue when I have different types of A. Ideally, I'd like to fully decouple A from B so I can pass any class like A that satisfies the same interface, but I cannot due to the exception(as it is not part of the interface itself)
In C++ I would have a header file with the definition of my Interface plus the exceptions which the concrete classes will implement. How is this usually solved in Python? Or said another way, what is the most pythonic approach?
I thought the following options:
1. create module with exceptions and maybe a base class/metaclass (the C++/Java way)
#common.py
class AErrorBase(Exception):
pass
class AIface(object):
def work(self):
raise NotImplemented()
.
#a.py
import common
class AError(common.AErrorBase):
pass
class A(common.AIface):
def work(self):
"""Throws AError when it is tired"""
raise AError()
.
#b.py
import common
class B(object):
def make_him_work(self, afected):
try:
afected.work()
except common.AErrorBase:
pass #This was expected
2. pass exception as an argument
#a.py
class AError(Exception):
pass
class A(object):
def work(self):
"""Throws AError when it is tired"""
raise AError()
.
#b.py
class B(object):
def make_him_work(self, afected, ex_type):
try:
afected.work()
except ex_type:
pass #This was expected
3. Exception as an attribute of the Class so it becomes part of the interface.
#a.py
class A(object):
def work(self):
"""Throws AError when it is tired"""
raise AError()
class AError(Exception):
pass
.
#b.py
class B(object):
def make_him_work(self, afected):
try:
afected.work()
except afected.AError:
pass #This was expected
4. Dont use exception, just a return code. !C days are back!
Any other option? What do you find more "pythonic"?
Edit: Added comments to clarify the purpose of the exception. It needs to be handled in B
Note: This might perfectly be that I am approaching the problem with my old C++ background, I just want to know how do you apply IoC in python when we have exceptions. Feel free to say all my approaches are garbage and I should do it in another way
My class would look like this:
class A(object):
def can_work(self):
"returns True if an A can work otherwise False (e.g. is an A is tired)"
return ...
def work(self):
assert not self._is_tired, "Test if self.can_work() first!"
...
This way you allow the users of A to test whether they should use work.
The assertion is useful for debugging and making sure you or others did not forget about the Interface.
Class B will use A as follows:
class B(object):
def make_him_work(self, afected):
if afected.can_work():
afected.work()
I find myself often wanting to structure my exception classes like this:
# legends.py
class Error(Exception): pass
class Rick(object):
class Error(Error): pass
class GaveYouUp(Error): pass
class LetYouDown(Error): pass
class Michael(object):
class Error(Error): pass
class BlamedItOnTheSunshine(Error): pass
class BlamedItOnTheMoonlight(Error): pass
I have only seen this pattern used in Django (DoesNotExist) and it makes so much sense. Is there anything I'm missing, why most people seem to favor top-level Exceptions?
edit
I would use these classes for versatile granularity, e.g:
import legends
try:
do_stuff()
except legends.Michael.Error:
blame_it_on_the_boogie()
except legends.Rick.GaveYouUp:
let_you_down()
except legends.Error:
pass
except Exception as e:
raise Hell()
This is the exact pattern used by Django for certain ORM-related exceptions.
The advantage is that you can have an except clause which checks against a type accessed through an instance:
rick = Rick()
try:
rick.roll()
except rick.GaveYouUp:
never()
except rick.LetYouDown:
never_ever()
This doesn't look that useful here, but if rick were a function parameter, then it would potentially be rather useful.
This is also extremely useful in writing generic code which raises the exceptions:
GoddamStar(object):
def sing(self,tune):
raise self.Error()
class Rick(GoddamStar):
class Error(Error): pass
class GaveYouUp(Error): pass
class LetYouDown(Error): pass
class Michael(GoddamStar):
class Error(Error): pass
class BlamedItOnTheSunshine(Error): pass
class BlamedItOnTheMoonlight(Error): pass
rick = Rick()
try:
rick.sing()
except Rick.GaveYouUp:
never()
except Michael.Error:
never_ever()
Django's exceptions generally all derive from global base classes, so that you can also have a catch-all clause which still switches on a type of exception, in case your rick is of an unknown (or otherwise unprovided for) class.
The reason why this isn't much more common is that (a) it doesn't work in early-bound languages, which attract most of the book writers (b) it's moderately rare that this is useful to the user, and so application writers likely figure they aren't going to need it.
If you want to raise e.g. BlamedItOnTheSunshine outside of Micheal you would have to call it by raise Micheal.BlamedItOnTheSunshine('error text').
e.g.:
class A:
class E(Exception): pass
def __init__(self): raise A('error in A')
class B:
def __init__(self): raise A.E('error in B')
in this Example A and B are not related, but if you have a relation like:
class Interpret(object):
class LetsYouDown(Exception): pass
def __init__(self): raise self.LetsYouDown("I'm not Rick!")
class Michael(Interpret):
class BlameItOnTheSunshine(Exception): pass
def __init__(self): raise self.BlameItOnTheSunshine("It's not the Moon!")
class Rick(Interpret):
class NeverEver(Exception): pass
def __init__(self): print "Never Ever!"
and want now something like:
try:
for superstar in [Interpret, Michael, Rick]:
star_in_show = superstar()
except superstar.LetsYouDown:
print "Where's Rick?"
except superstar.BlameItOnTheSunshine:
print "Must be Michael!"
you will get an Error i would call a Liskov's Principle violation.
So one of the main reason's (polymorphism) for using OOP is somewhat compromised. But it
doesn't necesarrily mean you can't or shouldn't use it. Just be aware of the limitations.
i hope that cleared my initial cryptical reservations up.