【问题标题】:How can I apply iter() to a pagination api?如何将 iter() 应用于分页 API?
【发布时间】:2019-05-23 02:52:49
【问题描述】:

我观看了 Raymond Hettinger 的 Idiomatic Python 谈话,并了解了 sentinel argumentiter()。 我想尝试将其应用于我正在迭代使用分页的 API 的一段代码(它是 Twilio,但与我的问题无关)。

我有一个返回的 API:数据列表和下一页 URL。当分页用尽时,下一页 URL 作为空字符串返回。我将获取函数编写为生成器,大致如下:

def fetch(url):
    while url:
        data = requests.get(url).json()
        url = data['next_page_uri']
        for row in data[resource]:
            yield row

此代码工作正常,但我想尝试删除 while 循环并将其替换为使用 next_page_uri 值作为标记参数的对 iter() 的调用。 或者,这可以写成yield from吗?

【问题讨论】:

  • 您不能在值的部分上使用iter。你可以编写一个适配器生成器,但它和你现在的一样复杂。
  • 值得注意的是,python3.6 会针对函数的示例版本抛出警告。在我的实际代码中,while 循环的内部位于 try-except to catch StopIteration`。
  • 您希望它 yield 行直到 'next_page_uri' 为空字符串?是否需要为每个next_page.发出新请求?
  • 是的,正如目前所写,它每次耗尽data[resource] 时都会发出一个新请求,然后继续从下一个request.get 产生额外的行。
  • @Sethish:这里有什么可以提高StopIteration

标签: python python-3.x sentinel yield-from


【解决方案1】:

我认为这可能是您的意思……但正如 cmets 中所述,它没有多大帮助:

def fetch_paged(url):
    while url:
        res = requests.get(url)
        res.raise_for_status()
        data = res.json()
        yield data
        url = data['next_page_uri']

def fetch(url):
    for data in fetch_paged(url):
        yield from data[resource]

(我借此机会拨打了raise_for_status() 的电话,如果不成功,我将拨打raise,即res.status_code < 400,回复)

不确定它是否“更好”,但如果您要大量重用 fetch_paged 功能,则可能

注意:许多其他 API 将此 next_page_uri 放入 standard ways 中的响应标头中,requests 库知道如何处理并通过 res.links 属性公开

【讨论】:

  • 谢谢!你是对的,这种类型的分页不太适合我在问题中链接的成语。我尝试了res.links,但可惜的是,Twilio api 不会以这种方式发送它们的值:ipdb> data <Response [200]> ipdb> data.links {}
猜你喜欢
  • 2017-12-30
  • 2011-02-18
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 2019-09-30
  • 2017-11-01
  • 2012-11-30
  • 1970-01-01
相关资源
最近更新 更多