我正在尝试从API获取所有地址的所有交易的数据。每个地址可以有几页交易记录,只有当我要求第一页时才能找到。
我有方法api.get_address_data(address, page)
和api.get_transaction_data(tx)
。
我要执行的同步代码如下所示:
def all_transaction_data(addresses):
for address in addresses:
data = api.get_address_data(address, page=0)
transactions = data.transactions
for n in range(1, data.total_pages):
next_page = api.get_address_data(address, page=n)
transactions += next_page.transactions
for tx in data.transactions:
yield api.get_transaction_data(tx)
我不在乎收到的交易顺序(准备好所有交易后,我必须重新排序)。我可以将所有数据容纳在内存中,但是请求非常少,所以我想尽可能多地并行执行。
完成此操作的最佳方法是什么?我当时在玩asyncio(API调用在我的控制之下,因此我可以将它们转换为async
),但是在交错层时遇到了麻烦:我最好的解决方案可以先获取所有地址,列出所有页面第二,最后大批量获得所有交易。我希望在准备好适当的输入数据后立即安排每个处理步骤,并将结果收集到一个大列表中(或从一个生成器生成)。
似乎我需要某种开放式任务队列,其中任务“ get-address”获取数据并排队一堆“ get-pages”任务,这些任务又将“ get-transaction”任务排队,然后只有这些被收集到结果列表中?
这可以通过asyncio完成吗?像gevent这样的东西会更合适吗,或者仅仅是一个普通的ThreadPoolExecutor?是否有比我到目前为止概述的方法更好的方法?
请注意,我想避免控制流反转,或者至少将其隐藏为实现细节。也就是说,此代码的调用者应该只能调用for tx in all_transaction_data()
,或者最糟糕的情况是async for
。