[Python-Dev] [Python-checkins] cpython (3.2): Updated logging cookbook with info on alternative format styles.

Nick Coghlan ncoghlan at gmail.com
Mon Feb 27 13:36:54 CET 2012


On Mon, Feb 27, 2012 at 9:04 PM, vinay.sajip <python-checkins at python.org> wrote:
> +There is, however, a way that you can use {}- and $- formatting to construct
> +your individual log messages. Recall that for a message you can use an
> +arbitrary object as a message format string, and that the logging package will
> +call ``str()`` on that object to get the actual format string. Consider the
> +following two classes::
> +
> +    class BraceMessage(object):
> +        def __init__(self, fmt, *args, **kwargs):
> +            self.fmt = fmt
> +            self.args = args
> +            self.kwargs = kwargs
> +
> +        def __str__(self):
> +            return self.fmt.format(*self.args, **self.kwargs)
> +
> +    class DollarMessage(object):
> +        def __init__(self, fmt, **kwargs):
> +            self.fmt = fmt
> +            self.kwargs = kwargs
> +
> +        def __str__(self):
> +            from string import Template
> +            return Template(self.fmt).substitute(**self.kwargs)
> +
> +Either of these can be used in place of a format string, to allow {}- or
> +$-formatting to be used to build the actual "message" part which appears in the
> +formatted log output in place of "%(message)s" or "{message}" or "$message".
> +It's a little unwieldy to use the class names whenever you want to log
> +something, but it's quite palatable if you use an alias such as __ (double
> +underscore – not to be confused with _, the single underscore used as a
> +synonym/alias for :func:`gettext.gettext` or its brethren).

This is the part I was thinking might be simplified by allowing a
"style" parameter to be passed to getLogger().

Consider StrFormatLogger and StringTemplateLogger classes that were
just wrappers around an ordinary Logger instance, and made the
relevant conversions to StrFormatMessage or StringTemplateMessage on
the caller's behalf.

Then (assuming the current getLogger() is available as _getLogger()),
you could just do something like:

    _LOGGER_STYLES = {
        "%": lambda x: x,
        "{": StrFormatLogger,
        "$": StringTemplateLogger,
    }

    def getLogger(name, style='%'):
        if style not in _STYLES:
            raise ValueError('Style must be one of: %s' %
','.join(_LOGGER_STYLES.keys()))
        return _LOGGER_STYLES[style](_getLogger())

Since each module should generally be doing its own getLogger() call
(or else should be documenting that it accepts an ordinary logger
instance as a parameter), it seems like this would allow fairly clean
use of the alternate styles without complicating each individual
logging operation.

(The xyzStyle approach used by formatters here won't work, since we
want different modules to be able to use different formatting styles.
However, ordinary inheritance should allow StrFormatLogger and
StringTemplateLogger to share most of their implementation)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list