Python调用zkSync API拉取交易 非0起始触发KeyError报错
问题根因
KeyError和你把起始偏移设为1001没有本质关联,只是偏移到1001之后刚好触发了你代码里两个硬编码的错误假设,从0开始运行不报错只是巧合——只要对应交易段满足触发条件,不管起始值设为多少都会崩溃:
- 错误假设1:每次API请求固定返回100条交易。你写死了循环变量i从0跑到99读取
data[i],但当起始偏移量接近该地址总交易数上限时,API返回的列表长度会小于100,甚至返回空列表,访问超出列表范围的索引时会直接报错。 - 错误假设2:所有交易的
tx字段下都存在orders键。zkSync API返回的交易包含充值、转账、提现、Swap等多种类型,只有Swap类交易的tx结构下才会携带orders字段,其他类型交易访问这个键会直接抛出KeyError。你从1001开始的交易段刚好包含非Swap类交易,就触发了报错。
修复方案
修复逻辑围绕两个问题点调整:
- 每次请求后按API实际返回的列表长度做循环,不硬编码循环100次;如果返回条数不足100,说明已经拉取到交易列表末尾,直接终止循环即可。
- 读取嵌套字段时用
dict.get()方法做安全读取,键不存在时返回默认值,避免直接访问不存在的键触发KeyError。 - 增加基础的请求异常捕获,避免API超时、返回非JSON格式、HTTP错误时函数直接崩溃。
修复后的完整代码:
import requests URL = "https://api.zksync.io/api/v0.1/account/0x2990d87e823d3cca83683207dcb2d5660debf376/history/" def lambda_handler(event, context): newdata = [] x = 1001 while x < 2000: newURL = f"{URL}{x}/100" # 捕获请求阶段异常 try: r = requests.get(url=newURL, timeout=10) r.raise_for_status() data = r.json() except Exception as e: print(f"拉取偏移{x}的交易失败: {str(e)}") x += 100 continue # 按实际返回的交易条数遍历 for i, tx_item in enumerate(data): tx_content = tx_item.get('tx', {}) parsed_tx = { 'nonce': tx_content.get('nonce'), 'created_at': tx_item.get('created_at'), 'serial': i, # 非Swap交易没有orders字段时自动赋值为None,不触发KeyError 'orders': tx_content.get('orders') } newdata.append(parsed_tx) # 返回条数不足100说明已经到列表末尾,提前终止循环 if len(data) < 100: break x += 100 return { 'statusCode': 200, 'body': newdata }
额外优化点
- 原代码中每次构造完Dict后调用
copy()是多余操作,每次循环都会重新生成新的字典对象,直接追加即可,不需要额外拷贝。 - 如果你只需要统计Swap类交易,可以在追加数据前加判断:
if parsed_tx['orders'] is not None:再执行append,过滤掉不需要的非Swap交易数据,减少内存占用。
内容的提问来源于stack exchange,提问作者Siddharth Hemrajani
相关产品推荐
相关产品推荐

