如何使logging.logger行为类似于print

8

假设我有一个logging.logger实例:

import logging
logger = logging.getLogger('root')
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
logging.basicConfig(format=FORMAT)
logger.setLevel(logging.DEBUG)

当我尝试像内置的print一样使用它,并具有动态数量的参数时,问题就出现了:

>>> logger.__class__
<class 'logging.Logger'>
>>> logger.debug("hello")
[<stdin>:1 -             <module>() ] hello
>>> logger.debug("hello","world")
Traceback (most recent call last):
  File "c:\Python2711\Lib\logging\__init__.py", line 853, in emit
    msg = self.format(record)
  File "c:\Python2711\Lib\logging\__init__.py", line 726, in format
    return fmt.format(record)
  File "c:\Python2711\Lib\logging\__init__.py", line 465, in format
    record.message = record.getMessage()
  File "c:\Python2711\Lib\logging\__init__.py", line 329, in getMessage
    msg = msg % self.args
TypeError: not all arguments converted during string formatting
Logged from file <stdin>, line 1

我该如何使用logging.Logger模拟打印行为?

1
只需将参数括在括号中,例如logger.debug(("hello","world"))。 - Andrey
Andrey:嗯,好的,我可以根据你的模式快速搜索和替换所有我的打印输出,干杯;-) - BPL
3个回答

2
基于@Jim原始答案的包装器:
import logging
import sys

_logger = logging.getLogger('root')
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
logging.basicConfig(format=FORMAT)
_logger.setLevel(logging.DEBUG)


class LogWrapper():

    def __init__(self, logger):
        self.logger = logger

    def info(self, *args, sep=' '):
        self.logger.info(sep.join("{}".format(a) for a in args))

    def debug(self, *args, sep=' '):
        self.logger.debug(sep.join("{}".format(a) for a in args))

    def warning(self, *args, sep=' '):
        self.logger.warning(sep.join("{}".format(a) for a in args))

    def error(self, *args, sep=' '):
        self.logger.error(sep.join("{}".format(a) for a in args))

    def critical(self, *args, sep=' '):
        self.logger.critical(sep.join("{}".format(a) for a in args))

    def exception(self, *args, sep=' '):
        self.logger.exception(sep.join("{}".format(a) for a in args))

    def log(self, *args, sep=' '):
        self.logger.log(sep.join("{}".format(a) for a in args))

logger = LogWrapper(_logger)

1
以这种方式,%lineno 将永远是 LogWrapper 中的行号,这可能是不希望的。 - Meta Fan
不要忘记在所有函数中添加 **kwargs。 - Eliav Louski

1

或者,定义一个接受*args的函数,然后在调用logger时将它们join起来:

def log(*args, logtype='debug', sep=' '):
    getattr(logger, logtype)(sep.join(str(a) for a in args))

我在这里添加了一个logtype以增加灵活性,但如果不需要可以将其删除。


太好了!我根据你的代码添加了我的答案,谢谢 ;) - BPL
1
"{}".format(a) 实际上只是一种丑陋而复杂的写法,等同于 str(a)。此外,如果你喜欢函数式编程风格,(f(x) for x in sequence) 可以简化为 map(f, sequence) - Bakuriu

-1
将sys.stdout设置为日志流。
例如: logging.basicConfig(level=logging.INFO, stream=sys.stdout)


我已经尝试使用Python 3.5.1进行测试,但仍然崩溃,错误提示为“在字符串格式化期间未转换所有参数”。 - BPL
如果我之前遇到过这种情况,那么引起这种情况的代码大概是这样的:('{} {}', variable1, variable2)。当我将其更改为'{} {}'.format(variable1, variable2)后,问题得到了解决。 - vds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接