Python does not come with reasonable logging defaults. The following code usually prints nothing.
import logging
logging.info("Hello world")
While it does provide `logging.basicConfig()` which kinda works (sets up stderr by default), I prefer setting this up myself.
This snippet sets up logging, adds a formatter and outputs error/info logs to the respective std streams.
Without setting up the filter for errors, log aggregators confuse a python error log with an info log. I've seen this in google stackdriver logs.
def remove_handlers():
logger = logging.getLogger()
for h in list(logger.handlers):
logger.removeHandler(h)
def setup_logging(filename=None, level="INFO"):
## Reset logger
remove_handlers()
logger = logging.getLogger()
formatter = logging.Formatter("%(asctime)s %(name)-12s %(levelname)-8s %(message)s")
consoleh = logging.StreamHandler(sys.stdout)
nonerror = lambda record: record.levelno != logging.ERROR
error = lambda record: record.levelno == logging.ERROR
errorh = logging.StreamHandler(sys.stderr)
errorh.setLevel(logging.ERROR)
errorh.setFormatter(formatter)
consoleh.setFormatter(formatter)
consoleh.addFilter(nonerror)
errorh.addFilter(error)
logger.addHandler(consoleh)
logger.addHandler(errorh)
logger.setLevel(level)
In notebooks/remote sessions, I prefer writing to files and not relying on the session.
import logging
import sys
def remove_handlers():
logger = logging.getLogger()
for h in list(logger.handlers):
logger.removeHandler(h)
def file_logging(filename, level="INFO"):
## Reset logger
remove_handlers()
logger = logging.getLogger()
fh = logging.FileHandler(f"{filename}.log")
formatter = logging.Formatter("%(asctime)s %(name)-12s %(levelname)-8s %(message)s")
fh.setFormatter(formatter)
logger.addHandler(fh)
logger.setLevel(level)
logging.info("Before setup")
setup_logging()
logging.info("Logs to stdout")
file_logging("test_logs")
logging.info("Logs to test_logs.log")
####
$ python test.py
INFO:root:Logs to stdout
2023-03-11 13:06:39,551 root INFO Logs to stdout
$ cat test_logs.log
2023-03-11 13:06:39,552 root INFO Logs to test_logs.log