Python Forum

Full Version: Operation result class
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
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?
(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).
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
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
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.
(Feb-25-2024, 10:12 AM)SirDonkey Wrote: [ -> ]some kind of a second hidden control flow
what do you mean by that?
(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.