【发布时间】:2013-07-17 14:38:48
【问题描述】:
所以我有这个带有集合people 的 RESTful API,可以这样调用:
http://example.com/people?lastname=smith
返回如下 JSON 响应:
{
"page": 0,
"next": 1,
"total": 5000000,
"people": [
{
"firstname": "John",
"lastname": "Smith",
"age": 32
},
{
"firstname": "Adam",
"lastname": "Smith",
"age": 84
},
...
}
我想编写一个 Python 生成器,它将从响应中产生每个人,当它到达最后一个人时,如果有下一页,它将使用 http://example.com/people?lastname=smith&page=1 请求下一页并继续迭代无缝地覆盖结果。生成的类调用很简单:
client = PeopleClient("http://example.com/people")
smiths = client.get_people_by_last_name("smith")
然后我就可以遍历smiths 中的每个“Smith”;如有必要,通过全部 500 万。
关于如何实现或是否有可能实现这一点的任何想法?
更新
使用来自@ali-afshar 的答案作为指导,这个实现应该适用于假设的 REST API:
import requests
class PeopleClient:
def __init__(self, url):
self._url = url
def _get_people(self, **kwargs):
return requests.get(self._url, params=kwargs)
def get_people_by_last_name(self, lastname):
current_page = 0
while current_page >= 0:
result = self._get_people(lastname=lastname, page=current_page)
for person in result.get("people", []):
yield person
current_page = result.get("next", -1)
【问题讨论】:
-
您可以使用 requests 包和内置的 json 包来解析 JSON。然后遍历所有名称。完成后,请求下一页。如果返回 404 则停止,否则继续上述操作。挖掘完所有内容后,只需遍历此列表即可。
-
@Vineet 认为使用生成器的重点不是在迭代之前处理整个数据集。我在示例中使用了 500 万这个数字来准确说明为什么您不会预先提出所有这些请求。
-
为什么没有人看到我已经知道 Python 生成器,并且我零打算首先将所有结果放入内存?以为我在我的问题中使用了“我想写一个 Python 生成器”和“yield”这样的短语来表达得很清楚。
-
@jeremyswitzer @ali-afshar 如果我们
yield result.get("people", [])多个人直接将有任何性能改进,但我同意我们需要更改使用生成器的 api 以及接受多人