Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Operation result class
#1
Hi,
I am pretty new to python and did some kind of return class which returns an outcome, user message and data when i call a method. I wonder if that is a common way of handling error/info/success messages. i add a simplified version of what i did.


class ResultCategories(enum.Enum):
    ERROR = enum.auto()
    WARNING = enum.auto()
    INFO = enum.auto()
    SUCCESS = enum.auto()

class OperationResult:
    def __init__(self, category: ResultCategories, message: str | None = None, data: any = None) -> None:
        self.category = category # Type of outcome, as defined by ResultCategories.
        self.message = message # Descriptive message of the outcome.
        self.data = data # Data associated with the operation's outcome.

class Messages:
    def __init__(self) -> None:
        self.current_priority = 0

    def show_message(self, category: ResultCategories, message_text: str, message_priority: int) -> None:

        if message_priority >= self.current_priority:

            if isinstance(category, ResultCategories):

                # Show the message. Choose style based on category.

                self.current_priority = message_priority
    
    def clear_message(self) -> None:

        # Clear the message.

        self.current_priority = 0


def do_something(self, test: bool) -> OperationResult:
        if test is True:
            return OperationResult(ResultCategories.ERROR, "some error message")
        
        # Do something
        data_back = "abc"
        return OperationResult(ResultCategories.SUCCESS, "everything went great", data_back)

messages = Messages()

result: OperationResult = do_something(False)
if result.category != ResultCategories.SUCCESS:
    messages.show_message(result.category, result.message, 50)
Is that a solid solution?
Reply
#2
(Feb-24-2024, 04:23 PM)SirDonkey Wrote: I wonder if that is a common way of handling error/info/success messages.
It is not common in Python. It is common in languages that don't handle exceptions such as C. The drawback of this way of programming is that every time a function calls do_something() it must check if the operation failed and take appropriate action. This adds much noise and tests in the code.

The common way in Python is to raise an exception when the operation fails
class OperationFailure(Exception):
    pass

def do_something(test: bool):
    if test:
        raise OperationFailure('some reason')
    else:
        return OperationResult('details')
The advantage is that client code can choose to let the error propagate to the caller instead of handling it immediately.
def publish_spam():
    print('spam spam spam')
    more_spam()

def more_spam():
    r = do_something(False)
    print(r.message)
    print('more spam')

publish_spam()
In this example, if do_something() fails in more_spam(), the error is propagated to publish_spam() and above. You can choose at which level you want to catch OperationFailure (or not).
« We can solve any problem by introducing an extra level of indirection »
Reply
#3
I think it is more "pythonic" to use exceptions. This looks like C++ code.

Using exceptions:
class ErrorException(Exception):
     """For when everything goes wrong."""

class WarningException(Exception):
    """For when you can get a value, but there may be a problem."""
    def __init__(self, message, value):
        self.message = message
        self.value = value

    def __str__(self):
        return self.message


def do_something(arg):
    match arg:
        case 0: 
            return 42
        case 1:
            raise ErrorException("Total disaster!")
    raise WarningException("Maybe you should try again with something other than", arg)


for arg in range(4):
    try:
        value = do_something(arg)
    except WarningException as e:
        print(arg, e, e.value)
    except ErrorException as e:
        print(arg, e)
    else:
        print(arg, "The answer to life the universe and everything is", value)
Output:
0 The answer to life the universe and everything is 42 1 Total disaster! 2 Maybe you should try again with something other than 2 3 Maybe you should try again with something other than 3
Reply
#4
As other already said - in python you can raise Exceptions and warnings
I am not sure how info is different from success so not sure what to suggest about it.
also if you need to return multiple values, instead of creating custom class you can use namedtuple
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
Thanks for all the answers!
I need to dive deeper into exceptions. Spontaniously what i do not like that much is the introduction of some kind of a second hidden control flow.
Reply
#6
(Feb-25-2024, 10:12 AM)SirDonkey Wrote: some kind of a second hidden control flow
what do you mean by that?
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#7
(Feb-25-2024, 10:12 AM)SirDonkey Wrote: what i do not like that much is the introduction of some kind of a second hidden control flow.
It is a "vertical" control flow, while the normal control flow is "horizontal". It allows you to program by assuming that things work. For example if you want to get a pack of beers, you need to put your shoes on, take your car, go to the store, find the aisle containing the beers, take a pack of beers, pay, take your car again, go back home. etc. All of these actions may fail individually but you don't want to write code to handle the innumerable failures that may happen. If anything fails, the relevant information is that you can't get the pack of beers and that's enough in many (if not most) cases. That's where exceptions come handy. If anything fails, an exception is thrown and that's what you get, but you can still write the code as if every operation was successful.
SirDonkey likes this post
« We can solve any problem by introducing an extra level of indirection »
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Using one method's result for another method in the same Class? btownboy 3 2,362 Sep-13-2020, 06:37 AM
Last Post: buran

Forum Jump:

User Panel Messages

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