1

I have my own exception classes inheriting from Exception class. I could check if type is in {..my exceptions list..}, but that seems problematic in my case. Is there any other way of checking if the exception is user-defined or Python's built-in exception. Thank you!

EDIT: The problem is that others can write their own exceptions or rename existing exceptions in their files, which I can't possibly keep track of. I need to log built-in exceptions, and ignore exceptions thrown because of user's fault. I need the checking in except block

try:
    # something
except Exception as god_knows_what_ex:
    # check if built-in
7
  • 1
    What's problematic about checking if it's in your exceptions list? I'd imagine that list can't be too long Commented Mar 20, 2019 at 14:04
  • Unless your userdefined exception has some attributes that one can check, i'm not sure Commented Mar 20, 2019 at 14:05
  • 2
    Alternatively, you can check that exception is built-in via exc in {.. built-in exceptions list ..} Commented Mar 20, 2019 at 14:06
  • @Sanyash Which is probably longer than the custom defined exceptions... Commented Mar 20, 2019 at 14:08
  • 5
    Sounds like an XY problem. Why do you care whether the exception is built-in? Commented Mar 20, 2019 at 14:08

4 Answers 4

3

I suspect that this question is due to the fact that your code has the following anti-pattern:

try:
    # bad code
except Exception as e:
    # catch all exceptions in the world, and try to
    # understand the type of e in superfluous ways

You should not (usually) check the type of the exception, instead you should use except with the minimal subset of relevant exception types:


try:
    # bad code
except (CustomException1, CustomException2):
    # handle exception

Or, if each exception type requires a different handling:

try:
    # bad code
except CustomException1:
    # handle CustomException1
except CustomException2:
    # handle CustomException2
Sign up to request clarification or add additional context in comments.

4 Comments

Does this offer a solution?
@SargsyanGrigor Yes. Do not check the type of the exception ("if type is in {..my exceptions list..}". It makes no sense and exceptions are not meant to be used this way. Instead, only use the relevant exceptions in the except clause like my answer suggests
@DeepSpace: Curious to know why that's considered an anti-pattern
@fountainhead Because it catches all exceptions, which means this except clause will hide exceptions that you would like to know about. Besides, why reinvent a mechanism that exists out of the box? Further reading: realpython.com/the-most-diabolical-python-antipattern
2

You could create your own custom exception class that inherits from Exception, and have your current exception classes inherit from that one.

So basically:

Exception
 - MyExceptionClass
    - MyExceptionClass1
    - MyExceptionClass2
 - Built-in exceptions

That way, you can check if an exception is an instance of your MyExceptionClass.

Then, you could do the following if you just want to know that thrown exception is user-defined:

try:
    method_that_can_throw_an_exception()
except MyExceptionClass:
    print('User-defined exception thrown')

1 Comment

Why would it beat the purpose DeepSpace?
1

A good design for this case is to define a base exception for your class. If someone wants to extend your module, make it crystal clear in your documentation that they have to use your exception type or extend it. Use the base class to create UserException. In the logging code, ignore UserException and log everything else.

Document this behavior.

Your approach probably won't work. You could start with this:

ex.__class__.__module__

which will return __builtin__ for predefined exceptions but not for those which are defined in the standard Python modules (*.py files in the library).

Also, how do you plan to support exceptions defined by other modules which users of your code have installed with pip?

Comments

0

Although the reasons of this question are questionable, here's an alternative that:

code.py:

#!/usr/bin/env python3

import sys
import json


class UserError:
    pass


class UserException(BaseException):
    pass


def builtin_exc(exc_inst):
    return getattr(getattr(exc_inst, "__class__", None), "__module__", None) == "builtins"


def main():
    user_err = UserError()
    user_exc = UserException()
    base_exc = BaseException()
    exc = Exception()
    ni_err = NotImplementedError()
    jsdec_err = json.JSONDecodeError("", "", 0)
    for item in [user_err, user_exc, base_exc, exc, ni_err, jsdec_err]:
        print("'{:s}' is builtin: {:}".format(item.__class__.__name__, builtin_exc(item)))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q055262562]> "e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.py
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32

'UserError' is builtin: False
'UserException' is builtin: False
'BaseException' is builtin: True
'Exception' is builtin: True
'NotImplementedError' is builtin: True
'JSONDecodeError' is builtin: False

3 Comments

Doesn't work for exceptions defined in standard Python modules like HTTPException in httplib.
@AaronDigulla: Is that a built in exception? (Hmm, I think the topic is "a bit" more complex than meets the eye).
He said he wanted to filter out "ignore exceptions thrown because of user's fault". I think that means "everything but a small set". He probably wants to log ZIP and various IO exceptions that are derived from Exception but are defined in Python modules, not in C code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.