4

Here's my exception class that is using raise:

class SCE(Exception):
    """
    An error while performing SCE functions.
    """
    def __init__(self, value=None):
        """
        Message: A string message or an iterable of strings.
        """
        if value is None:
            self._values = []
        elif isinstance(value, str):
            self._values = [value]
        else:
            self._values = list(value)

    def __raise__(self):
        print('raising')
        if not len(self._values):
            return

    def __str__(self):
        return self.__repr__()

    def __iter__(self):
        return iter(self._values)

    def __repr__(self):
        return repr(self._values)

Currently if I raise this exception with no value I get traceback followed by:

__main__.SCE: []

Instead of what I expected which was:

raising
>>>

How do you overload raise?

orokusaki
  • 55,146
  • 59
  • 179
  • 257
  • Not worth the down vote, so here is +1 to you. – erisco Feb 01 '10 at 23:33
  • 1
    If you subclass Exception (or indeed anything much), you should also remember to call the base class's `__init__` method in the subclass's. – bobince Feb 01 '10 at 23:53

3 Answers3

3

As the other answer says, there is no __raise__ special method. There was a thread in 2004 on comp.lang.python where someone suggested adding such a method, but I don't think there was any followup to that. The only way I can think of to hook exception raising is either by patching the interpreter, or some kind of source or bytecode rewriting that inserts a function call next to the raise operation.

mithrandi
  • 1,630
  • 9
  • 27
1

There is no such special method __raise__ (at least none that I have ever heard of or that I can find in the Python documentation).

Why do you want to do this? I can't think of any reason why you want custom code be be executed when the exception is raised (as opposed to either when the exception is constructed, which you can do with the __init__ method, or when the exception is caught, which you can do with an except block). What is your use case for this behavior, and why do you expect that Python supports it?

Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135
  • 1
    Um... that page doesn't contain the string "__raise__" – Will McCutchen Feb 01 '10 at 23:40
  • 3
    @Will McCutchen: I think that's the point. If it's not in the docs, it doesn't exist, right? – Daniel Pryden Feb 02 '10 at 00:00
  • Haha, I'm an idiot. I originally read that as "Why don't you check the documentation at this link" and expected to be enlightened. Now I read it as "Why don't you helpfully link to this documentation?" Sorry! – Will McCutchen Feb 02 '10 at 05:02
  • @DanielPryden I'd leverage this when I'm using a python library and it's raising an exception when it shouldn't be. Overloading `raise` would allow to perform some action based on the error and instruct the underlying code to continue working as if no exception was raised – Mikhail Jun 24 '15 at 22:52
  • here's an example where it would be useful: https://stackoverflow.com/a/42000305/202168 instead of the `re_raise` method and calling `e.re_raise()` you could just `raise e` – Anentropic Apr 04 '18 at 14:38
  • Another example would be exception classes which do some logging _when they are raised_. Currently we have to add that code to the point where they're raised, or as a hack in the `__init__` of the exception, which is wrong as it's perfectly valid to instantiate an exception without raising it – Anentropic Aug 16 '18 at 14:21
  • It would be visually tidier to move that logic checking whether to raise or not inside the smart exception class itself. But this is a bad idea, because it will be a huge surprise for new readers of the code, and even once educated, there is no way for the reader to see, for any raise in the program, whether it really raises or not. Explicit is better than implicit. – Jonathan Hartley Aug 20 '20 at 20:58
0

As others have stated, there is no such private method __raise__. Nothing prevents defining one. For example:

#!/usr/bin/env python3


class MyClass(object):
    def __init__(self, raise_exceptions=False):
        self.raise_exceptions = raise_exceptions

    def __raise__(self, err=None):
        print(err, flush=True)
        if self.raise_exceptions:
            raise err

    def run(self):
        try:
            assert False, 'assertion False'
        except Exception as err:
            self.__raise__(err)


if __name__ == '__main__':
    MyClass(raise_exceptions=False).run()
    MyClass(raise_exceptions=True).run()

Here is the output:

$ python3 my_class.py
assertion False
assertion False
Traceback (most recent call last):
  File "my_class.py", line 22, in <module>
    MyClass(raise_exceptions=True).run()
  File "my_class.py", line 17, in run
    self.__raise__(err)
  File "my_class.py", line 11, in __raise__
    raise err
  File "my_class.py", line 15, in run
    assert False, 'assertion False'
AssertionError: assertion False

Process finished with exit code 1
Nomen Nescio
  • 347
  • 1
  • 7