Python Logging
Python Logging#
Use the source…Luke
A good place to look is the standard library’s logging
module/file.
Most IDEs will go there when you cmd + click
on import logging
.
I was reading:
#---------------------------------------------------------------------------
# Level related stuff
#---------------------------------------------------------------------------
#
# Default levels and level names, these can be replaced with any positive set
# of values having corresponding names. There is a pseudo-level, NOTSET, which
# is only really there as a lower limit for user-defined levels. Handlers and
# loggers are initialized with NOTSET so that they will log all messages, even
# at user-defined levels.
#
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
So the default logging level is 0
or NOTSET
.
You can verify this yourself:
logger = logging.getLogger(__name__)
logger.level
>>>> 0
So by default all log messages should be sent…
However not all logging will print a message - only levels warning and above
Set the Logging Level from Environment Variable#
LOGLEVEL = os.environ.get('LOGLEVEL', 'WARNING').upper()
logging.basicConfig(level=LOGLEVEL)
Another way is:
logging.basicConfig(level=logging.getLevelName(log_level))
Both are fine but the top one have less calls to _nameToLevel
Logging Patterns#
The Big Tarp Pattern#
try:
main_loop()
except Exception:
logger.exception("Fatal error in main loop")
- A broad catch-all
- It can raise a number of different exceptions and you don’t want the program to terminate
- Preferred to log and continue
- The
exception
method captures the full stacktrace and logs it - By default,
logger.exception
uses the log level ofERROR
.
The “Pinpoint” Pattern#
try:
places = find_burrito_joints(criteria)
except BurritoCriteriaConflict as err:
logger.warn("Cannot resolve conflicting burrito criteria: {}".format(err.message))
places = list()
- Handling a specific exception
The Message and Raise Pattern#
try:
something()
except SomeError:
logger.warn("...")
raise
- You are not actually handling the exception
- With an existing higher level handler, you want to log that the error occurred, or the meaning of it, at a certain place in the code.
- Most Useful in troubleshooting
The Cryptic Message Antipattern#
try:
something()
except Exception:
logger.error("...")
It is hard to figure out where in the code it actually broke.
In that instance it is best to set exc_info
try:
something()
except Exception:
logger.error("something bad happened", exc_info=True)
The Most Diabolical Python Antipattern#
try:
something()
except Exception:
pass
- No useful exception information is generated
- Completely hides that there is something wrong
- You may not even know a variable name was typed wrong -
NameError
is hidden