Python Forum
Creating custom exceptions that co-operate
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Creating custom exceptions that co-operate
#1
The Python docs state:

Quote:Programs may name their own exceptions by creating a new exception class (see Classes for more about Python classes). Exceptions should typically be derived from the Exception class, either directly or indirectly.

For example:

 class StudentValueError(Exception):
     pass
Quote:When creating a module that can raise several distinct errors, a common practice is to create a base class for exceptions defined by that module, and subclass that to create specific exception classes for different error conditions:

class MissingStudentValueError(StudentValueError):
    def __init__(self, expression, error_message):
        self.error_message = error_message
        self.expression = expression # expression that raise the exception.
2 problems, it doesn't co-operate, and it violates LSP (I can't create an instance of MissingStudentValueError with zero arguments, like I can with just Exception alone).

I fixed it like this:

class StudentValueError(Exception):
    """Base class exceptions for Student Values"""
    def __init__(self, *args):
        super().__init__(*args)


class MissingStudentValue(StudentValueError):
    def __init__(self, expression="", error_message="", *args):
        super().__init__(*args)
        self.error_message = error_message
        self.expression = expression # expression that raise the exception.
        
    def __str__(self):
        return "Message: {0} Parameters: {1}".format(self.error_message, self.expression)
I reached out to Yury Selivanov, a Python Core Developer and he stated:

Quote:Calling "super().__init__(*args)" is the exactly right approach.

I can now create an instance of MissingStudentValue without any arguments, and the subclass takes whatever arguments are necessary, and the rest is passed up the call chain to the base class Exception.

Have I created a custom exception that doesn't violate LSP, co-operates, and is considered best practice?
Reply
#2
What's LSP? I have a degree in computer science and five years' experience with software engineering and I'm unfamiliar with the acronym.

That said, I'm confused by your final code. You don't show the use of MissingStudentValue but I'm doubtful that you pass more than two arguments to it (after all, why would you?). What you probably meant to do was to pass your two named arguments into super so that when the stack trace is printed, it shows your message, e.g.
Output:
>>> raise Exception("what", "hey") Traceback (most recent call last): File "<stdin>", line 1, in <module> Exception: ('what', 'hey')
That said, what are you doing that actually needs super()?
Reply
#3
(Mar-19-2019, 01:27 AM)micseydel Wrote: What's LSP? I have a degree in computer science and five years' experience with software engineering and I'm unfamiliar with the acronym.
Liskov substitution principle

Quote:That said, what are you doing that actually needs super()?
I wanted my classes to co-operate, and in the future you may want to pass in additional arguments.

Quote:That said, I'm confused by your final code. You don't show the use of MissingStudentValue but I'm doubtful that you pass more than two arguments to it (after all, why would you?)
I thought it was unnecessary, because we all know how to raise exceptions, and it wasn't relevant to my overall problem.
Reply
#4
If you take as first the arguments and then keyword arguments, the Exception could be used like a normal exception.
If you call the class with msg or err, you get the user defined output.
Otherwise you get the output from Exception.

class ChildException(Exception):
    def __init__(self, *args, msg=None, err=None):
        self.msg = msg
        self.err = err
        super().__init__(*args)
    def __str__(self):
        if self.msg or self.err:
            return f'Message: "{self.msg}" Code: {self.err}'
        else:
            return super().__str__()
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
(Mar-19-2019, 02:51 PM)DeaD_EyE Wrote: If you take as first the arguments and then keyword arguments, the Exception could be used like a normal exception.
If you call the class with msg or err, you get the user defined output.
Otherwise you get the output from Exception.

class ChildException(Exception):
    def __init__(self, *args, msg=None, err=None):
        self.msg = msg
        self.err = err
        super().__init__(*args)
    def __str__(self):
        if self.msg or self.err:
            return f'Message: "{self.msg}" Code: {self.err}'
        else:
            return super().__str__()

I realized I screwed up the ordering of *args in the constructor parameters. Thanks for your feedback, it's exactly what I wanted.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Custom method to handle exceptions not working as expected gradlon93 3 944 Dec-22-2022, 07:12 PM
Last Post: deanhystad
  PiCamera - print exceptions? korenron 2 792 Dec-15-2022, 10:48 PM
Last Post: Larz60+
  Class exceptions DPaul 1 1,259 Mar-11-2022, 09:01 AM
Last Post: Gribouillis
  is this a good way to catch exceptions? korenron 14 4,593 Jul-05-2021, 06:20 PM
Last Post: hussaind
  Python, exceptions KingKhan248 6 2,945 Nov-15-2020, 06:54 AM
Last Post: buran
  Split string between two different delimiters, with exceptions DreamingInsanity 2 1,979 Aug-24-2020, 08:23 AM
Last Post: DreamingInsanity
  handling 2 exceptions at once Skaperen 2 2,262 Jun-27-2020, 08:55 AM
Last Post: Yoriz
  remove spaces with exceptions catosp 4 2,364 May-29-2020, 09:32 AM
Last Post: catosp
  Looking for advice and Guidance on Exceptions used within Functions paul41 1 2,108 Nov-14-2019, 12:33 AM
Last Post: Larz60+
  multi-line messages in raised exceptions? Skaperen 3 7,223 Aug-01-2019, 02:17 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020