How can I more easily suppress previous exceptions when I raise my own exception in response?

Question:

Consider

try:
   import someProprietaryModule
except ImportError:
   raise ImportError('It appears that <someProprietaryModule> is not installed...')

When run, if someProprietaryModule is not installed, one sees:

(traceback data)
ImportError: unknown module: someProprietaryModule

During handling of the above exception, another exception occurred:

(traceback data)
ImportError: It appears that <someProprietaryModule> is not installed...

Perhaps I don’t want the “During handling of the above exception…” line (and the lines above it) to appear. I could do this:

_moduleInstalled = True
try:
   import someProprietaryModule
except ImportError:
   _moduleInstalled = False
if not _moduleInstalled: 
   raise ImportError('It appears that <someProprietaryModule> is not installed...')

But that feels like a bit of a hack. What else might I do?

Asked By: Hammerite

||

Answers:

In Python 3.3 and later raise ... from None may be used in this situation.

try:
   import someProprietaryModule
except ImportError:
   raise ImportError('It appears that <someProprietaryModule> is not installed...') from None

This has the desired results.

Answered By: Hammerite

This can be done like this in Python 2.7 and Python 3:

try:
    import someProprietaryModule
except ImportError as e:
    raised_error = e

if isinstance(raised_error, ImportError):
    raise ImportError('It appears that <someProprietaryModule> is not installed...')
Answered By: user60561

You can try logging module as well

Original Answer:
Perhaps I don’t want the "During handling of the above exception…" line (and the lines above it) to appear.

import logging

try:
    import someProprietaryModule
    
except Exception as e:
    
    if hasattr(e, 'message'):
        logging.warning('python2')
        logging.error(e.message)
        
    else:
        
        logging.warning('python3')
        logging.error('It appears that <someProprietaryModule> is not installed...')

gives

WARNING:root:python3
ERROR:root:It appears that <someProprietaryModule> is not installed...

[Program finished]

Edit:

import logging

class MyExceptionType(Exception):
    """Base class for other exceptions"""
    pass

try:
    from someProprietaryModule import *
except Exception as e:
        logging.warning('python3')
        logging.exception("Failed to import <someProprietaryModule>. Is it installed?", exc_info=False)
        raise MyExceptionType from e

logging.exception will emit the stacktrace alongside the localized error message, which makes it quite useful.

Casting an exception to a string to print it removes 90% of the useful information.

Silently suppressing exceptions is almost always an error and is most commonly a footgun.

Answered By: Subham