【问题标题】:Logger behaving erratically, throwing odd error记录器行为异常,抛出奇怪的错误
【发布时间】:2015-01-15 21:02:48
【问题描述】:

我一直在尝试使用一个简单的记录器,但我无法确定这里出了什么问题:

dlogger = logging.getLogger('Logger')
dlogger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(
    LOG_FILENAME, maxBytes=50000, backupCount=5)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
dlogger.addHandler(handler)

# ...

dlogger.info('%d successes. %d errors.', counter, error)

上面的代码在运行时会产生这个错误:

Traceback (most recent call last):
  File "/usr/lib/python2.7/logging/__init__.py", line 851, in emit
     msg = self.format(record)
 File "/usr/lib/python2.7/logging/__init__.py", line 724, in format
    return fmt.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 467, in format
    s = self._fmt % record.__dict__
 ValueError: unsupported format character '(' (0x28) at index 3

具有相同 ValueError 的其他问题似乎都无法解释我的情况。怎么回事?!

不仅如此,在我运行包含此日志消息的脚本后,它会显示以下行为:

8 successes. 0 errors.
8 successes. 0 errors.
8 successes. 0 errors.
2015-01-15 16:30:07,539 - INFO - 8 successes. 0 errors.

记录器只能触发一次,但出于某种原因,它会产生所有这些消息。

添加:即使我将消息简化为字符串(没有格式化计数),它仍然会在我的日志中发送五六行重复行。

甚至稍后添加:好的,我想我可以解释多个日志记录:我在调试时一直在重新加载模块,并且我认为它产生了多个记录器,即使我认为我在重新加载期间覆盖了前一个记录器,它们仍然可以工作.

【问题讨论】:

  • 您的重新加载并没有创建多个记录器(如果已经存在一个同名的记录器,它将被重用),但是会注册多个处理程序。如果一个记录器有多个处理程序,使用该记录器记录的消息将由附加到它的每个处理程序处理。
  • 我可以解释这一点的唯一方法是在格式字符串中的 %( 之间有一些无关的、可能不可见的非 ASCII 字符。例外提到索引 3 - 但是,您的 ( 应该在索引 1 处。您能否通过将格式字符串从此问题复制并粘贴回您的代码来验证这一点,完全替换您当前拥有的代码行?
  • 另外:如果您的文件顶部有 # -*- encoding: <encoding> 前导码来声明源代码编码,请暂时将其删除 - Python 会抱怨文件中的任何非 ASCII 字符.
  • @LukasGraf 同时,我从记录器中提取了字符串并将两个数字格式化,然后我将此字符串传递给记录器,我似乎没有收到该错误消息了。可能当我从食谱上剪切和粘贴它时,我拿起了一些看不见的角色,就像你建议的那样。感谢您解释这种可能性。

标签: python python-2.7 logging


【解决方案1】:

看这里:https://docs.python.org/2/library/logging.html#logging.Logger.debug

我猜你在这一行中的一个变量:

formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

为空。这将使格式字符串变成这样: %() 这将给出您描述的错误。

尝试打印出这些变量

【讨论】:

  • 这些都是内置的LogRecord attributes,不能为空。它们由 Python 的日志记录系统本身提供。
  • 嗯,好的,这是一个很好的线索。但是我上面使用的代码直接来自Logging cookbook 我认为 asctime、levelname 和 message 是日志模块内部的名称,因此将始终提供 levelname 和 asctime,我只需要提供“消息。”
猜你喜欢
  • 2020-11-06
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
相关资源
最近更新 更多