如何调试Python日志配置文件错误

2 投票
2 回答
2010 浏览
提问于 2025-04-18 02:24

我在代码中添加了Python的日志模块,想要摆脱一堆乱七八糟的打印语句,但现在遇到了配置错误,错误信息也不太好理解。

Traceback (most recent call last):
  File "HDAudioSync.py", line 19, in <module>
    logging.config.fileConfig('../conf/logging.conf')
  File "/usr/lib64/python2.6/logging/config.py", line 84, in fileConfig
    handlers = _install_handlers(cp, formatters)
  File "/usr/lib64/python2.6/logging/config.py", line 162, in _install_handlers
    h = klass(*args)
TypeError: __init__() takes at most 5 arguments (21 given)

我的配置文件里没有任何内容给出21个参数。

这是我的配置文件:

[loggers]
keys=root,main, sftp, jobapi

[handlers]
keys=console, logfile, syslog

[formatters]
keys=simple, timestamp

[logger_root]
level=NOTSET
handlers=logfile

[logger_main]
level=DEBUG
handlers=console, logfile, syslog
propagate=1
qualname=main


[logger_sftp]
level=DEBUG
handlers=console, logfile, syslog
propagate=1
qualname=sftp


[logger_jobapi]
level=DEBUG
handlers=console, logfile, syslog
propagate=1
qualname=jobapi

[handler_console]
class=StreamHandler
level=DEBUG
formatter=simple
args=(sys.stdout,)

[handler_logfile]
class=FileHandler
level=DEBUG
formatter=timestamp
args=('../log/audiosync.log')


[handler_syslog]
class=FileHandler
level=WARN
formatter=timestamp
args=('../log/audiosync.sys.log')

[formatter_simple]
format=%(levelname)s - %(message)s

[formatter_timestamp]
format=%(asctime)s - %(name)s -%(levelname)s - %(message)s

这是我在主模块中的日志初始化代码:

import logging
import logging.config
import logging.handlers

logging.config.fileConfig('../conf/logging.conf')
logger = logging.getLogger('main')

我并不是特别想知道我哪里做错了(虽然知道了也不错),我更想要的是一种调试这个问题的方法。

谢谢。

2 个回答

0

寻找关键词

错误信息的最后两行提到了 handler 这个词(handler = ..._install_handlers)。这给了你一个起点,可以去查看配置文件中的处理器定义。

到处寻找匹配的值 无处不在

如果一个函数需要5个参数,但你给了它超过4倍的参数,那就说明某些东西没有按照你预期的方式解析。尤其是当你快速查看配置文件时,根本没有看到接近那个数字的东西。

我发现这种不一致的一个主要原因是,当函数期待一个列表、元组或对象时,你却传入了一个字符串。底层代码可能会把这个字符串拆分成字符,然后用这些字符作为参数。

在你的情况下,我能找到的第一个选项是在配置文件的这个部分:

[handler_syslog]
class=FileHandler
level=WARN
formatter=timestamp
args=('../log/audiosync.sys.log')

这里没有单独的21个字符的字符串,但如果你把参数前面的 ../ 去掉,就剩下 log/audiosync.sys.log,这正好是一个21个字符的字符串。

使用调试工具

这就是它们存在的目的。使用 pdb,或者像 PyCharmPyDev 这样的可视化调试工具。这样,你可以逐行查看代码,并检查变量的值。

改变日志级别

一些模块允许你设置它们的日志级别。你可以把它设置为 DEBUG,这样就能看到开发者记录的所有信息。这可以帮助你跟踪应用程序运行时的流程。我觉得这在 ConfigParser 模块中可能不可用,但在某些情况下是可以的。

如果一切都失败了,就看看源代码

Python 的源代码可以在网上找到。如果你遇到一些半模糊的错误信息,觉得很难理解上下文,你可以下载源代码,手动查看代码。

6

你可以查看Python的源代码来研究这些问题。大部分库都是用Python写的,读起来相对简单,不需要了解解释器的内部细节。hg.python.org提供了一个方便的网页界面,可以让你浏览代码库。我没找到2.6版本的分支,但在当前版本的第147行有相关的代码。

你会看到args是通过eval生成的,它从配置文件中每个handler_*部分的args键获取值。然后,这个args变量通过展开操作(*)被转换成klass()函数的参数。

在你的配置文件中,有这一行:

args=('../log/audiosync.log')

这是一串20个字符的字符串,它被展开成一个包含单个字符的元组。再加上传给__init__self对象,就形成了错误信息中的21个参数。你缺少一个结尾的逗号,这样才能形成一个只有1个元素的元组:

args=('../log/audiosync.log',)
                            ^-- missing

handler_syslog部分也有同样的错误。

撰写回答