Identifying exception categories in an excepthook() handler

Hi. Attempting (unsuccessfully so far) to classify exceptions in a sys.excepthook() handler, with the general philosophy being:

  • if it’s a language / library issue, restart the app
  • if it’s an OS issue, die properly.

I expect I should be able to detect whether the exception Type is e.g. in OSError’s subclasses, but the details are a mystery.

Attempt 1: Do I need to instantiate an OSError to inspect these?

>>> e=OSError()
>>> e.__subclasses__()
AttributeError: ‘OSError’ object has no attribute ‘__subclasses__’

Better solutions welcomed !

Base classes do not know about derived classes. Its the other way around.

In general you cannot know from the type of an exception what the correct way to handle it is.

Assuming that the app (service) has past its tests the you will want to do:

  1. Log the full stack trace
  2. Restart the service
  3. Add code to be explicitly handle the exception and recover appropiately.

I use the OS service manager to deal with the (2) restart issue.
In my case that is either app specific logic to fork off a new worker, or use systemd .service unit to express restart behaviour, detect fast restarts etc

Thanks. I’m puzzled because:

… speaks of ‘certain object types’ possessing a function to return their subclasses.

Unfortunately, elsewhere in the forums use of this method is discouraged due to various problems:

But there’s a hint to use the issubclass() built-in:

So I’ll try that next.

Sure they do.

>>> class MyInt(int):
...     pass
... 
>>> int.__subclasses__()
[<class 'bool'>, <enum 'IntEnum'>, <enum 'IntFlag'>, <class 'sre_constants._NamedIntConstant'>, <class '__main__.MyInt'>]
1 Like

sys.excepthook is called with three arguments:

  • the exception class;
  • an exception instance;
  • and a traceback object.

You don’t need to instantiate the exception class, because you have already been passed the instance that was raised.

If your hook function is defined like this:

def myexceptionhook(ex_type, ex_inst, tb):
    ...

then you can decide what to do by inspecting any of those three arguments. For example:

if issubclass(ex_type, OSError):
    # do whatever is appropriate for an OSError

Note that OSError is usually raised from file operations that failed, e.g. file not found, insufficient permissions to open a file, attempting to write to a file on read-only media, etc.

Noted with appreciation, Steven.

I’ve progressed to a working prototype that uses:

if issubclass(exc_type, OSError):

… successfully.

Since I am deliberately triggering them in some places, I needed to identify SystemExit exceptions for different handling.

They only deliver a result code and no caller context as the sub-types of Exception do.

Case closed :slight_smile: