需知
升级feapder,保证feapder是最新版,若BUG仍然存在,则详细描述问题
pip install --upgrade feapder
问题
在 feapder/db/mysqldb.py 的 MysqlDB.init() 方法中,连接失败时的错误日志存在格式化参数数量不匹配的问题。
When the MySQL connection fails in MysqlDB.init(), the error logging has a format argument mismatch bug.
截图
代码
except Exception as e:
log.error(
"""
连接失败:
ip: {}
port: {}
db: {}
user_name: {}
user_pass: {}
exception: {}
""".format(
ip, port, db, user_name, user_pass, charset, e
)
)
问题分析 / Analysis
格式字符串中有 6 个 {} 占位符,但 .format() 传入了 7 个参数:
| 占位符位置 |
实际填充的值 |
期望填充的值 |
ip: {} |
ip ✅ |
ip |
port: {} |
port ✅ |
port |
db: {} |
db ✅ |
db |
user_name: {} |
user_name ✅ |
user_name |
user_pass: {} |
user_pass ✅ |
user_pass |
exception: {} |
charset(如 "utf8mb4") ❌ |
真正的异常对象 e |
| (无对应占位符) |
真正的异常对象 e(被静默丢弃) |
— |
实际影响 / Impact
用户看到的错误日志是:
连接失败:
ip: localhost
port: 3306
db: py_spider
user_name: root
user_pass: root
exception: utf8mb4 ← 实际是 charset 的值,不是异常信息!
真正的异常(如 SSLError: [ASN1: NOT_ENOUGH_DATA] not enough data)被完全丢弃,用户被严重误导,无法定位真实原因。
The real exception (e.g. SSL errors, auth failures, connection refused) is silently dropped, making debugging extremely difficult.
附带问题:except 块未重新抛出异常,产生僵尸对象
except 块记录日志后没有 raise,导致即使连接失败,MysqlDB() 仍然返回一个没有 connect_pool 属性的"僵尸"对象。后续任何方法调用(execute、find、add 等)都会触发第二个误导性错误:
error:'MysqlDB' object has no attribute 'connect_pool'
两个 Bug 叠加的效果:用户先看到一个错误信息被篡改的日志,紧接着又被 AttributeError 进一步误导,完全找不到北。
受影响的调用点(共 8 处)
# 所有这些无参调用在连接失败时都会产生僵尸对象:
feapder/commands/create/create_item.py:29 self._db = MysqlDB()
feapder/commands/create/create_table.py:23 self._db = MysqlDB()
feapder/core/base_parser.py:128 self._mysqldb = mysqldb or MysqlDB()
feapder/core/base_parser.py:224 batch_info = MysqlDB().find(sql) # 立即崩
feapder/core/spiders/batch_spider.py:117 self._mysqldb = MysqlDB()
feapder/core/spiders/task_spider.py:114 self._mysqldb = MysqlDB()
feapder/network/user_pool/normal_user_pool.py:67 self._mysqldb = MysqlDB()
feapder/pipelines/mysql_pipeline.py:25 self._to_db = MysqlDB()
其中 base_parser.py:224 最严重——临时创建后立即调用 .find(),连接失败即崩。
修复建议 / Proposed Fix
- 修正格式化参数数量:
except Exception as e:
log.error(
"""
连接失败:
ip: {}
port: {}
db: {}
user_name: {}
user_pass: {}
charset: {}
exception: {}
""".format(
ip, port, db, user_name, user_pass, charset, e
)
)
- 建议
except 块重新抛出异常,避免产生僵尸对象:
except Exception as e:
log.error(
"""
连接失败:
ip: {}
port: {}
db: {}
user_name: {}
user_pass: {}
charset: {}
exception: {}
""".format(
ip, port, db, user_name, user_pass, charset, e
)
)
raise # ← 重新抛出,避免返回不完整的对象
补充说明 / Additional Context
这是一个存在已久的隐蔽 bug。只有当 MySQL 连接失败时才会触发,而连接失败往往恰恰是最需要准确错误信息来排查问题的场景。这个 bug 导致用户在排查连接问题时被完全误导。
建议一并检查代码库中是否有其他类似的格式化参数不匹配问题。
环境 / Environment
- feapder version: 1.9.3(最新版)
- Python: 3.9
- OS: Windows 11
- mysql: 5.7.33-log
需知
升级feapder,保证feapder是最新版,若BUG仍然存在,则详细描述问题
问题
在 feapder/db/mysqldb.py 的 MysqlDB.init() 方法中,连接失败时的错误日志存在格式化参数数量不匹配的问题。
When the MySQL connection fails in MysqlDB.init(), the error logging has a format argument mismatch bug.
截图
代码
问题分析 / Analysis
格式字符串中有 6 个
{}占位符,但.format()传入了 7 个参数:ip: {}ip✅ipport: {}port✅portdb: {}db✅dbuser_name: {}user_name✅user_nameuser_pass: {}user_pass✅user_passexception: {}charset(如 "utf8mb4") ❌ee(被静默丢弃)实际影响 / Impact
用户看到的错误日志是:
真正的异常(如
SSLError: [ASN1: NOT_ENOUGH_DATA] not enough data)被完全丢弃,用户被严重误导,无法定位真实原因。The real exception (e.g. SSL errors, auth failures, connection refused) is silently dropped, making debugging extremely difficult.
附带问题:except 块未重新抛出异常,产生僵尸对象
except块记录日志后没有raise,导致即使连接失败,MysqlDB()仍然返回一个没有connect_pool属性的"僵尸"对象。后续任何方法调用(execute、find、add等)都会触发第二个误导性错误:两个 Bug 叠加的效果:用户先看到一个错误信息被篡改的日志,紧接着又被
AttributeError进一步误导,完全找不到北。受影响的调用点(共 8 处)
其中
base_parser.py:224最严重——临时创建后立即调用.find(),连接失败即崩。修复建议 / Proposed Fix
except块重新抛出异常,避免产生僵尸对象:补充说明 / Additional Context
这是一个存在已久的隐蔽 bug。只有当 MySQL 连接失败时才会触发,而连接失败往往恰恰是最需要准确错误信息来排查问题的场景。这个 bug 导致用户在排查连接问题时被完全误导。
建议一并检查代码库中是否有其他类似的格式化参数不匹配问题。
环境 / Environment