classification
Title: add argument for formatter to logging.Handler and subclasses in logging module
Type: enhancement Stage:
Components: Library (Lib) Versions: Python 3.6
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: underrun, vinay.sajip
Priority: normal Keywords:

Created on 2013-08-08 20:15 by underrun, last changed 2015-11-11 22:30 by underrun. This issue is now closed.

Messages (5)
msg194706 - (view) Author: Derek Wilson (underrun) Date: 2013-08-08 20:15
It is common when setting up a logger to create both a handler and a formatter. Nice format strings make logging better. Like this:

>>> fmt_string = "%(asctime)s [%(levelname)-9s] %(name)s: %(message)s"

We would use it like so: 

>>> from logging import getLogger, StreamHandler, Formatter
>>> logger = getLogger('mypackage.mymodule')
>>> handler = StreamHandler()
>>> formatter = Formatter(fmt_string)
>>> handler.setFormatter(formatter)
>>> logger.addHandler(handler)
>>> logger.warning('she called out a warning...')

But its nice to separate adding handlers from using loggers. so in mymodule I might do:

>>> logger = getLogger('mypackage.mymodule')
>>> logger.warning('do not pass go...')

and in whatever entry point cares about logging from mypackage (like a cli or another module importing my package that wants log data) I would do:

>>> base_logger = getLogger('mypackage')
>>> handler = StreamHandler()
>>> formatter = Formatter(fmt_string)
>>> handler.setFormatter(formatter)
>>> base_logger.addHandler(handler)

but usually, at this point, i don't care about this base_logger at all and i've got a bunch of refs to things i don't need anymore - the only purpose of all this code is to handle any logging that may be done elsewhere in the package.

If handlers allowed passing in a formatter into __init__, then we could reduce the above to something like this:

>>> getLogger('mypackage').addHandler(StreamHandler(
        fmt=Formatter(fmt_string)))

Using a kwarg would make it so we don't need to worry about existing argument order so that should be completely backward compatible.

It'd be extra friendly if Handler could introspect fmt and see if it is an instance str and if so create a Formatter in itself ... that way we could do:

>>> getLogger('mypackage').addHandler(StreamHandler(fmt=fmt_string))

This would reduce the barrier to entry to customizing logging functionality and might go a long way toward increasing effective use of the same.
msg194818 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2013-08-10 16:54
I suggest that the declarative configuration approach of logging.config.dictConfig() be used for configurations which can't be handled by basicConfig().

I don't propose to enhance the Handler API as suggested, as at the very least every handler would need to be changed to accommodate the new kwarg. Also, this isn't going to work for third-party handlers which are out there already, since they won't necessarily recognise a new kwarg.
msg194971 - (view) Author: Derek Wilson (underrun) Date: 2013-08-12 17:16
dictConfig and fileConfig are nice for static needs, but when I want to quickly enable a complex (but not complicated) logging flow I find it just as tedious as the current situation with the direct API.

> ... as at the very least every handler would need to be changed to accommodate the new kwarg

Adding a keyword only argument to the base handler and the other handler classes is a nearly trivial change in terms of lines and complexity of the code.

> Also, this isn't going to work for third-party handlers which are out there already, since they won't necessarily recognise a new kwarg.

I don't see that as a problem. If 3rd party handlers are intelligent then they will include **kargs in their __init__ and pass that forward to the initialization of their parent. If they haven't done so then nothing changes for them and they just support exactly the same features they supported previously.
msg194994 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2013-08-12 19:30
> If 3rd party handlers are intelligent

It's not an ideal world. Sorry, but I think this change is too invasive to consider. I can't believe this change is really needed - logging has been around since 2002 and this has never been raised before.
msg254499 - (view) Author: Derek Wilson (underrun) Date: 2015-11-11 22:30
> It's not an ideal world. Sorry, but I think this change is too invasive to consider.

Obviously its not ideal, which is why my suggestion doesn't require intelligent 3rd party libraries and is explicitly not invasive. As I said in my previous comment, using a keyword only argument means: "If [3rd party libraries] haven't [properly handled **kwargs] then nothing changes for them and they just support exactly the same features they supported previously."

The upshot is it is not invasive and no one needs to care unless they want to use the new functionality.

As far as this change being needed or not, nothing "needs" to be made easier to use if it is possible to use it. But that isn't really a good reason not to improve things.

I honestly think that part of the reason this hasn't come up is because the advanced features of logging are so difficult to use that people just don't use it to its fullest extent. On top of that, when learning python, logging is way harder to grok than it should be for someone new to python.

Logging and unittest are two of the most important libraries for new pythonistas to learn, but they are also some of the most nebulous, stateful, magical, java-like, complicated, verbose, and difficult to master packages in python.

They've been around for a while for sure - but doesn't that rather mean that they could use an update?

I'm willing to submit a patch if it has the smallest chance of being considered?
History
Date User Action Args
2015-11-11 22:30:13underrunsetmessages: + msg254499
versions: + Python 3.6, - Python 3.4
2013-08-12 19:30:23vinay.sajipsetstatus: open -> closed

messages: + msg194994
2013-08-12 17:16:05underrunsetstatus: pending -> open

messages: + msg194971
2013-08-10 16:54:12vinay.sajipsetstatus: open -> pending

nosy: + vinay.sajip
messages: + msg194818

resolution: wont fix
2013-08-08 20:15:37underruncreate