Logging variable data with new format string

后端 未结 9 2224
别那么骄傲
别那么骄傲 2020-11-28 03:09

I use logging facility for python 2.7.3. Documentation for this Python version say:

the logging package pre-dates newer formatting options such as str

9条回答
  •  臣服心动
    2020-11-28 03:14

    Here is another option that does not have the keyword problems mentioned in Dunes' answer. It can only handle positional ({0}) arguments and not keyword ({foo}) arguments. It also does not require two calls to format (using the underscore). It does have the ick-factor of subclassing str:

    class BraceString(str):
        def __mod__(self, other):
            return self.format(*other)
        def __str__(self):
            return self
    
    
    class StyleAdapter(logging.LoggerAdapter):
    
        def __init__(self, logger, extra=None):
            super(StyleAdapter, self).__init__(logger, extra)
    
        def process(self, msg, kwargs):
            if kwargs.pop('style', "%") == "{":  # optional
                msg = BraceString(msg)
            return msg, kwargs
    

    You use it like this:

    logger = StyleAdapter(logging.getLogger(__name__))
    logger.info("knights:{0}", "ni", style="{")
    logger.info("knights:{}", "shrubbery", style="{")
    

    Of course, you can remove the check noted with # optional to force all messages through the adapter to use new-style formatting.


    Note for anyone reading this answer years later: Starting with Python 3.2, you can use the style parameter with Formatter objects:

    Logging (as of 3.2) provides improved support for these two additional formatting styles. The Formatter class been enhanced to take an additional, optional keyword parameter named style. This defaults to '%', but other possible values are '{' and '$', which correspond to the other two formatting styles. Backwards compatibility is maintained by default (as you would expect), but by explicitly specifying a style parameter, you get the ability to specify format strings which work with str.format() or string.Template.

    The docs provide the example logging.Formatter('{asctime} {name} {levelname:8s} {message}', style='{')

    Note that in this case you still can't call the logger with the new format. I.e., the following still won't work:

    logger.info("knights:{say}", say="ni")  # Doesn't work!
    logger.info("knights:{0}", "ni")  # Doesn't work either
    

提交回复
热议问题