Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Modern Python Cookbook

You're reading from   Modern Python Cookbook 133 recipes to develop flawless and expressive programs in Python 3.8

Arrow left icon
Product type Paperback
Published in Jul 2020
Publisher Packt
ISBN-13 9781800207455
Length 822 pages
Edition 2nd Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Steven F. Lott Steven F. Lott
Author Profile Icon Steven F. Lott
Steven F. Lott
Arrow right icon
View More author details
Toc

Table of Contents (18) Chapters Close

Preface 1. Numbers, Strings, and Tuples 2. Statements and Syntax FREE CHAPTER 3. Function Definitions 4. Built-In Data Structures Part 1: Lists and Sets 5. Built-In Data Structures Part 2: Dictionaries 6. User Inputs and Outputs 7. Basics of Classes and Objects 8. More Advanced Class Design 9. Functional Programming Features 10. Input/Output, Physical Format, and Logical Layout 11. Testing 12. Web Services 13. Application Integration: Configuration 14. Application Integration: Combination 15. Statistical Programming and Linear Regression 16. Other Books You May Enjoy
17. Index

Concealing an exception root cause

In Python 3, exceptions contain a root cause. The default behavior of internally raised exceptions is to use an implicit __context__ to include the root cause of an exception. In some cases, we may want to deemphasize the root cause because it's misleading or unhelpful for debugging.

This technique is almost always paired with an application or library that defines a unique exception. The idea is to show the unique exception without the clutter of an irrelevant exception from outside the application or library.

Getting ready

Assume we're writing some complex string processing. We'd like to treat a number of different kinds of detailed exceptions as a single generic error so that users of our software are insulated from the implementation details. We can attach details to the generic error.

How to do it...

  1. To create a new exception, we can do this:
    >>> class MyAppError(Exception):
    ...     pass
    

    This creates a new, unique class of exception that our library or application can use.

  2. When handling exceptions, we can conceal the root cause exception like this:
    >>> try:
    ...     None.some_method(42)
    ... except AttributeError as exception:
    ...     raise MyAppError("Some Known Problem") from None
    

In this example, we raise a new exception instance of the module's unique MyAppError exception class. The new exception will not have any connection with the root cause AttributeError exception.

How it works...

The Python exception classes all have a place to record the cause of the exception. We can set this __cause__ attribute using the raise Visible from RootCause statement. This is done implicitly using the exception context as a default if the from clause is omitted.

Here's how it looks when this exception is raised:

>>> try:
...     None.some_method(42)
... except AttributeError as exception:
...     raise MyAppError("Some Known Problem") from None
Traceback (most recent call last):
  File "/Applications/PyCharm CE.app/Contents/helpers/pycharm/docrunner.py", line 139, in __run
    exec(compile(example.source, filename, "single",
  File "<doctest examples.txt[67]>", line 4, in <module>
    raise MyAppError("Some Known Problem") from None
MyAppError: Some Known Problem

The underlying cause has been concealed. If we omit from None, then the exception will include two parts and will be quite a bit more complex. When the root cause is shown, the output looks like this:

Traceback (most recent call last):
  File "<doctest examples.txt[66]>", line 2, in <module>
    None.some_method(42)
AttributeError: 'NoneType' object has no attribute 'some_method'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/Applications/PyCharm CE.app/Contents/helpers/pycharm/docrunner.py", line 139, in __run
    exec(compile(example.source, filename, "single",
  File "<doctest examples.txt[66]>", line 4, in <module>
    raise MyAppError("Some Known Problem")
MyAppError: Some Known Problem

This shows the underlying AttributeError. This may be an implementation detail that's unhelpful and better left off the printed display of the exception.

There's more...

There are a number of internal attributes of an exception. These include __cause__, __context__, __traceback__, and __suppress_context__. The overall exception context is in the __context__ attribute. The cause, if provided via a raise from statement, is in __cause__. The context for the exception is available but can be suppressed from being printed.

See also

  • In the Leveraging the exception matching rules recipe, we look at some considerations when designing exception-handling statements.
  • In the Avoiding a potential problem with an except: clause recipe, we look at some additional considerations when designing exception-handling statements.
You have been reading a chapter from
Modern Python Cookbook - Second Edition
Published in: Jul 2020
Publisher: Packt
ISBN-13: 9781800207455
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at AU $24.99/month. Cancel anytime