如何使用逗号作为千位分隔符记录数字?

时间:2017-08-14 23:14:24

标签: python logging string-formatting

现在是将所有打印转换为我正在维护的库中的日志记录调用的时候了。一些打印调用正在使用str.format,如下所示(简化):

>>> n = 4000000
>>> print(f"this bird wouldn't voom if you put {n:,} volts through it!")
this bird wouldn't voom if you put 4,000,000 volts through it!

当我尝试记录它时:

>>> log.warning("this bird wouldn't voom if you put %d, volts through it!", n)
WARNING:root:this bird wouldn't voom if you put 4000000, volts through it!

似乎这没有正确指定千位分隔符。在使用Python的stdlib日志记录模块所需的%-formatting语法时,如何指定千位分隔符?

目前正在使用此解决方法,它确实提供了所需的输出,但似乎错误,因为变量首先使用str.format格式化,然后再次格式化为字符串,而不是直接记录为数字:

>>> log.warning("this bird wouldn't voom if you put %s volts through it!", format(n, ','))
WARNING:root:this bird wouldn't voom if you put 4,000,000 volts through it!

1 个答案:

答案 0 :(得分:2)

这是logging的限制,并且documentation中的(至少有一个地方)实际提到了这个限制:

  

logging.debug(msg, *args, **kwargs)

     

在根记录器上记录级别为DEBUG的消息。 msg是消息格式字符串,args是使用字符串格式化运算符合并到 msg的参数。 (请注意,这意味着您可以使用格式字符串中的关键字以及单个字典参数。)

(强调我的)

但字符串格式化运算符%不支持thousand seperators

然而,您可以从官方cookbook

调整配方
import logging

class Message(object):
    def __init__(self, fmt, args):
        self.fmt = fmt
        self.args = args

    def __str__(self):
        return self.fmt.format(*self.args)

class StyleAdapter(logging.LoggerAdapter):
    def __init__(self, logger, extra=None):
        super(StyleAdapter, self).__init__(logger, extra or {})

    def log(self, level, msg, *args, **kwargs):
        if self.isEnabledFor(level):
            msg, kwargs = self.process(msg, kwargs)
            self.logger._log(level, Message(msg, args), (), **kwargs)

logger = StyleAdapter(logging.getLogger(__name__))

def main():
    # this changed
    logger.warning("this bird wouldn't voom if you put {:,} volts through it!", 4000000)

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    main()
  

WARNING:__main__:如果你通过4,000,000伏电压,那只鸟就不会出现这种情况!

这实际上是从"Use of alternative formatting styles"部分的最后一个示例逐字复制(我刚刚更改了消息)。

就个人而言,我会选择你的format(n, ',')解决方案。它可能不完美,但它不需要设置自定义LoggerAdapter来打印不同的千位分隔符。