I've been writing Python for years, but I've only just started using it in bigger programs than just simple server scripts. This means I now also want to use a more advanced logging system. To make things simple I created the following logger:
import logging from inspect import getframeinfo, stack logger = logging.getLogger() formatter = logging.Formatter('%(asctime)s %(name)-7s %(levelname)-8s %(message)s') file_handler = logging.FileHandler('mm.log') file_handler.setFormatter(formatter) stream_handler = logging.StreamHandler() stream_handler.setFormatter(formatter) logger.addHandler(file_handler) logger.addHandler(stream_handler) logger.setLevel(logging.INFO) def l(*args, **kwargs): level = kwargs.get('level', 'info').lower() assert level in ('debug', 'info', 'warning', 'error', 'critical') caller = getframeinfo(stack()) file_line = "%s:%d - " % (caller.filename, caller.lineno) logger_input = file_line + ' '.join([str(a) for a in args]) getattr(logger, level)(logger_input)
This logs to stdout and to a logfile and also logs the filename and the line number from which the log is made. It can be used as follows:
from tools import l l('Log message') # logs in INFO by default l('Log message one', 'log message two') # log multiple messages l('Log message', level='critical') # log in critical level
which creates something like this:
2017-10-10 20:47:16,170 root INFO test.py:5 - Log message 2017-10-10 20:47:16,171 root INFO test.py:14 - Log message one log message two 2017-10-10 20:47:16,171 root CRITICAL test.py:116 - Log message
I import this in all the other files of my program and it seems to work quite ok. It enables to me to run the program from the command line and see the output, as well as running it as a daemon and seeing the output in the log files later. Furthermore, it's easy for debugging because it also logs the filename and line number, and I can easily change the default logging level with one line. Lastly, the use of a single
l shortens the way of logging things. All in all, I'm quite happy with it.
I'm unsure if this is for some reason stupid though. Maybe there are situations which I can't oversee right now which would make this mess up things. Maybe the default conversion to strings is not smart for some reason?
Could anybody enlighten me as to what could be wrong with this or how it could be made better/more robust? All tips are welcome!