Python Web3监听合约事件报错,程序无法继续运行求助
问题排查与修复方案
先梳理你代码里几个致命的问题,以及对应的修复方式:
1. 递归调用参数缺失
listenForTokens()函数定义要求传入lastRunTime参数,但你在finally块里递归调用时未传参,这会直接触发参数不匹配的错误,是必现的报错点。
2. 异常捕获无有效调试信息
你用except:捕获所有异常但只打印“Error skipped”,完全看不到具体错误类型和堆栈信息——根本没法知道是节点连接失败、合约事件不存在,还是其他问题导致的报错。
3. 事件循环适配问题
Python 3.10+版本中,asyncio.get_event_loop()的行为有变化,直接调用可能抛出RuntimeError,建议改用更简洁稳定的asyncio.run()。
4. 未定义的tokenLoop函数
代码中调用了tokenLoop但未提供实现,若这个函数本身存在问题,也会导致后续执行失败。
修改后的可调试代码示例
import asyncio import datetime # 假设你已正确初始化contract对象 # from web3 import Web3 # contract = Web3(Web3.HTTPProvider("你的节点地址")).eth.contract(address="合约地址", abi=合约ABI) def listenForTokens(lastRunTime): # 捕获具体异常并打印详情 try: event_filter = contract.events.PairCreated.createFilter(fromBlock='latest') except Exception as e: print(f"创建事件过滤器失败: {type(e).__name__} - {str(e)}") return # 终止当前执行,避免无意义递归 # 用asyncio.run简化事件循环管理 try: asyncio.run(tokenLoop(event_filter, 0, lastRunTime)) except Exception as e: print(f"事件循环执行失败: {type(e).__name__} - {str(e)}") finally: # 递归时传入更新后的时间参数 new_run_time = datetime.datetime.now() listenForTokens(new_run_time) async def tokenLoop(event_filter, counter, lastRunTime): # 补充你的业务逻辑,示例为监听新事件 while True: new_events = event_filter.get_new_entries() for event in new_events: print(f"捕获新PairCreated事件: {event}") await asyncio.sleep(3) # 避免频繁查询节点 lastRunTime = datetime.datetime.now() listenForTokens(lastRunTime) input("按回车退出程序...")
关键修复说明
- 将宽泛的
except:改为except Exception as e,打印具体异常类型和信息,这是排查问题的核心前提。 - 递归调用时传入更新后的
lastRunTime参数,解决参数缺失错误。 - 用
asyncio.run()替代旧的事件循环写法,适配Python新版本,避免循环初始化异常。 - 补充了
tokenLoop的示例实现,确保调用的函数存在。
额外排查方向
- 检查
contract对象初始化是否正确:节点连接是否正常、合约ABI和地址是否匹配。 - 确认合约中确实存在
PairCreated事件,大小写和拼写必须完全一致。 - 若使用第三方节点(如Infura),确认节点支持事件过滤操作(部分免费节点有功能限制)。
内容的提问来源于stack exchange,提问作者James McKillan
相关产品推荐
相关产品推荐

