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?
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.
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...')
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.
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?
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.
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...')
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.