发布日期: 2025-10-21
版本: V2.5.1 (Hotfix)
错误信息:
File "monitor_whales.py", line 809, in start_monitoring
self.update_task = asyncio.ensure_future(self._periodic_data_update())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: There is no current event loop in thread 'MainThread'.原因分析:
asyncio.ensure_future()需要在事件循环中调用start_monitoring()是同步方法,没有运行中的事件循环- 无法在同步上下文中创建异步任务
解决方案: 使用独立线程运行定期更新任务:
# 修改前(错误)
self.update_task = asyncio.ensure_future(self._periodic_data_update())
# 修改后(正确)
import threading
def run_periodic_update():
asyncio.run(self._periodic_data_update())
update_thread = threading.Thread(target=run_periodic_update, daemon=True)
update_thread.start()
logging.info("✅ 定期更新任务已启动(后台线程)")优势:
- ✅ 后台线程独立运行,不阻塞主程序
- ✅
daemon=True确保程序退出时自动停止 - ✅ 使用
asyncio.run()创建新的事件循环 - ✅ 简化代码,移除不必要的
update_task引用
在每次批量获取账户数据后,显示成功/失败统计:
日志输出示例:
2025-10-21 22:28:49,909 | INFO | ✅ 数据更新完毕,耗时: 39.50秒
2025-10-21 22:28:49,910 | INFO | 📊 统计: 成功 17 个, 失败 0 个 (总计 17 个)失败时输出:
2025-10-21 22:28:49,909 | INFO | ✅ 数据更新完毕,耗时: 39.50秒
2025-10-21 22:28:49,910 | INFO | 📊 统计: 成功 15 个, 失败 2 个 (总计 17 个)
2025-10-21 22:28:49,911 | WARNING | ⚠️ 获取失败的地址:
2025-10-21 22:28:49,912 | WARNING | - 0x35d1151e...
2025-10-21 22:28:49,913 | WARNING | - 0x15b32566...实现代码:
# 统计成功和失败的数量
success_count = sum(1 for result in results if result is not None)
fail_count = sum(1 for result in results if result is None)
logging.info(f"✅ 数据更新完毕,耗时: {elapsed:.2f}秒")
logging.info(f"📊 统计: 成功 {success_count} 个, 失败 {fail_count} 个 (总计 {len(addresses)} 个)")
# 如果有失败的地址,记录日志
if failed_addresses:
logging.warning(f"⚠️ 获取失败的地址:")
for addr in failed_addresses:
logging.warning(f" - {addr[:10]}...")效果:
- ✅ 一眼就能看到获取成功率
- ✅ 快速定位失败的地址
- ✅ 方便排查网络问题
删除:
# __init__
- self.update_task = None
# start_monitoring
- self.update_task = asyncio.ensure_future(self._periodic_data_update())
# KeyboardInterrupt
- if self.update_task:
- self.update_task.cancel()
- logging.debug("已取消定期更新任务")新增:
# start_monitoring
+ import threading
+ def run_periodic_update():
+ asyncio.run(self._periodic_data_update())
+
+ update_thread = threading.Thread(target=run_periodic_update, daemon=True)
+ update_thread.start()
+ logging.info("✅ 定期更新任务已启动(后台线程)")新增:
# update_and_generate_report_async
+ # 统计成功和失败的数量
+ success_count = sum(1 for result in results if result is not None)
+ fail_count = sum(1 for result in results if result is None)
+
+ logging.info(f"✅ 数据更新完毕,耗时: {elapsed:.2f}秒")
+ logging.info(f"📊 统计: 成功 {success_count} 个, 失败 {fail_count} 个 (总计 {len(addresses)} 个)")
+
+ # 构建结果字典
+ all_account_data = {}
+ failed_addresses = []
+ for addr, data in zip(addresses, results):
+ if data:
+ all_account_data[addr] = data
+ else:
+ failed_addresses.append(addr)
+
+ # 如果有失败的地址,记录日志
+ if failed_addresses:
+ logging.warning(f"⚠️ 获取失败的地址:")
+ for addr in failed_addresses:
+ logging.warning(f" - {addr[:10]}...")================================================================================
正在获取用户初始仓位信息...
================================================================================
2025-10-21 22:28:10,414 | INFO | 🚀 开始更新 17 个地址的数据...
2025-10-21 22:28:10,414 | INFO | 🔄 刷新账户数据: 0x5b5d5120...
... (获取过程)
2025-10-21 22:28:49,909 | INFO | ✅ 数据更新完毕,耗时: 39.50秒
2025-10-21 22:28:49,910 | INFO | 📊 统计: 成功 17 个, 失败 0 个 (总计 17 个)
2025-10-21 22:28:49,913 | INFO | ================================================================================
2025-10-21 22:28:49,913 | INFO | 📊 多空持仓统计
2025-10-21 22:28:49,913 | INFO | ================================================================================
2025-10-21 22:28:49,913 | INFO | 🟢 做多: 68 个持仓, 总价值: $267,143,058.89 (15.4%)
2025-10-21 22:28:49,913 | INFO | 🔴 做空: 177 个持仓, 总价值: $1,466,406,559.75 (84.6%)
2025-10-21 22:28:49,913 | INFO | 📈 多空比: 0.18
2025-10-21 22:28:49,913 | INFO | ================================================================================
2025-10-21 22:28:49,921 | INFO | ✅ 持仓信息已保存到: positions/positions_20251021_222810.html
2025-10-21 22:28:49,922 | INFO | ✅ 定期更新任务已启动(后台线程) ← 新增
================================================================================
正在订阅用户事件...
================================================================================2025-10-21 22:06:50,277 | INFO | ✅ 数据更新完毕,耗时: 11.11秒
2025-10-21 22:06:50,278 | INFO | 📊 统计: 成功 15 个, 失败 2 个 (总计 17 个) ← 新增
2025-10-21 22:06:50,279 | WARNING | ⚠️ 获取失败的地址: ← 新增
2025-10-21 22:06:50,280 | WARNING | - 0x35d1151e... ← 新增
2025-10-21 22:06:50,281 | WARNING | - 0x15b32566... ← 新增原因:
start_monitoring()是同步方法- 后续代码需要阻塞等待WebSocket连接
- 定期更新任务需要在后台独立运行
对比方案:
| 方案 | 优势 | 劣势 |
|---|---|---|
asyncio.ensure_future() |
简洁 | ❌ 需要运行中的事件循环 |
asyncio.create_task() |
标准 | ❌ 需要运行中的事件循环 |
| 线程 | ✅ 独立运行 ✅ 不需要事件循环 ✅ 简单可靠 |
略微增加资源消耗 |
选择线程的原因:
- ✅ 定期更新是独立任务,不需要与主程序交互
- ✅
daemon=True确保程序退出时自动清理 - ✅ 代码更简洁,不需要管理事件循环
步骤:
# 1. 更新代码
git pull
# 2. 重启监控
python3 monitor_whales.py无需修改配置,完全向后兼容!
- Python 3.12.10
- macOS (darwin 24.4.0)
- 17个监控地址
- ✅ 程序正常启动
- ✅ 初始化数据获取成功
- ✅ 定期更新任务正常运行
- ✅ WebSocket连接稳定
- ✅ 统计信息准确显示
- ✅ 无RuntimeError错误
BUGFIX_V2.5.1.md- 之前的bug修复SUMMARY_V2.5.1.md- V2.5.1总结README.md- 完整使用文档
版本: V2.5.1 (Hotfix)
发布日期: 2025-10-21
状态: ✅ 稳定版