Skip to content

Instantly share code, notes, and snippets.

@kojiromike
Last active December 13, 2021 16:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kojiromike/a719ed8e0ebd424b61484bbd2adecf5b to your computer and use it in GitHub Desktop.
Save kojiromike/a719ed8e0ebd424b61484bbd2adecf5b to your computer and use it in GitHub Desktop.
A demonstration of Python exception context and logging
#!/usr/bin/env python3
import sys
import logging
from pprint import pprint
LOG = logging.getLogger('Exception Logging Demo')
logging.basicConfig(format='[%(asctime)s] %(name)s:%(levelname)s %(message)s', level='INFO')
print("This is a demonstration of how Python manages exception information.")
print("sys.exc_info() returns a tuple of whatever exception is in the global context.")
print("https://docs.python.org/3/library/sys.html#sys.exc_info")
print()
print("=" * 80)
print()
print("When there's no exception in context, it looks like this:")
print("-" * 80)
pprint(sys.exc_info())
print("-" * 80)
print()
try:
raise RuntimeError("A runtime error occurred")
except RuntimeError:
print("In an exception handler (`except` block), there's an exception in context.")
print("(You don't have to name an exception to access it from sys.exc_info().)")
print("It looks like this:")
print("-" * 80)
pprint(sys.exc_info())
print("-" * 80)
print()
print("Once outside the except block, the exception is no longer in context.")
print("Here's sys.exc_info() again:")
print("-" * 80)
pprint(sys.exc_info())
print()
print("=" * 80)
print()
print("The python logger has a special facility for logging exceptions.")
print("When you pass `exc_info=True` to a logger call, it will cause the logger")
print("to display the exception from sys.exc_info (if any).")
print("With default formatting, it will print the exception message and the traceback.")
print("You can also pass a different exception, and of course the logger can be configured")
print("to format the exception and its traceback differently.")
print("https://docs.python.org/3/library/logging.html#logging.debug")
print()
print("=" * 80)
print()
print("-" * 80)
LOG.info("logger.info, with no exception in context, exc_info=True", exc_info=True)
print("-" * 80)
print()
try:
raise RuntimeError("A second runtime error occurred")
except RuntimeError:
print("-" * 80)
LOG.info("logger.info, with an exception in context, exc_info=True", exc_info=True)
print("-" * 80)
print()
print()
print("=" * 80)
print("logger.exception is just logger.error with exc_info implicitly set to True")
This is a demonstration of how Python manages exception information.
sys.exc_info() returns a tuple of whatever exception is in the global context.
https://docs.python.org/3/library/sys.html#sys.exc_info
================================================================================
When there's no exception in context, it looks like this:
--------------------------------------------------------------------------------
(None, None, None)
--------------------------------------------------------------------------------
In an exception handler (`except` block), there's an exception in context.
(You don't have to name an exception to access it from sys.exc_info().)
It looks like this:
--------------------------------------------------------------------------------
(<class 'RuntimeError'>,
RuntimeError('A runtime error occurred'),
<traceback object at 0x110680f80>)
--------------------------------------------------------------------------------
Once outside the except block, the exception is no longer in context.
Here's sys.exc_info() again:
--------------------------------------------------------------------------------
(None, None, None)
================================================================================
The python logger has a special facility for logging exceptions.
When you pass `exc_info=True` to a logger call, it will cause the logger
to display the exception from sys.exc_info (if any).
With default formatting, it will print the exception message and the traceback.
You can also pass a different exception, and of course the logger can be configured
to format the exception and its traceback differently.
https://docs.python.org/3/library/logging.html#logging.debug
================================================================================
--------------------------------------------------------------------------------
[2021-12-13 11:55:15,556] Exception Logging Demo:INFO logger.info, with no exception in context, exc_info=True
NoneType: None
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
[2021-12-13 11:55:15,556] Exception Logging Demo:INFO logger.info, with an exception in context, exc_info=True
Traceback (most recent call last):
File "/Users/michaelsmith/dev/minerva-service/./exc_info_demo.py", line 60, in <module>
raise RuntimeError("A second runtime error occurred")
RuntimeError: A second runtime error occurred
--------------------------------------------------------------------------------
================================================================================
logger.exception is just logger.error with exc_info implicitly set to True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment