Gcloud Discovery API分页无nextPageToken?无法获取全部Compute资源
解决Google Compute API获取所有磁盘/镜像的分页问题
首先得说,你现在的代码里有两个关键问题,导致既拿不到目标资源(磁盘/镜像),也没法正确完成分页:
问题1:调用了错误的API资源
你当前用的是compute.instances().list(),这是用来列虚拟机实例的接口,完全不是你需要的磁盘或镜像。要获取磁盘得用compute.disks().list(),获取镜像则是compute.images().list()——另外镜像还要注意区分私有镜像(你的项目内)和公共镜像(比如Debian、Ubuntu官方镜像,需要指定对应公共项目名,比如debian-cloud)。
问题2:分页代码漏掉了.execute()
你循环里的这行代码:
resp = compute.instances().list(project=PROJECT_NAME, pageToken=resp["nextPageToken"])
只是创建了一个请求对象,根本没实际发送请求去获取数据,必须加上.execute()才能拿到带资源列表的响应。另外,循环里的items应该用追加而不是直接覆盖,不然每次只会保留当前页的内容,之前的资源都会丢失。
修正后的代码示例
获取项目内所有磁盘
from googleapiclient import discovery PROJECT_NAME = "你的项目ID" compute = discovery.build('compute', 'v1') all_disks = [] # 发起首次请求 resp = compute.disks().list(project=PROJECT_NAME).execute() if "items" in resp: all_disks.extend(resp["items"]) # 处理分页 while "nextPageToken" in resp: # 必须加.execute()执行请求! resp = compute.disks().list( project=PROJECT_NAME, pageToken=resp["nextPageToken"] ).execute() if "items" in resp: all_disks.extend(resp["items"]) # 现在all_disks里就是所有磁盘数据了 print(f"共获取到 {len(all_disks)} 个磁盘")
获取所有镜像(私有+公共)
如果要同时拿到自己项目的私有镜像和官方公共镜像,可以分开请求后合并结果:
all_images = [] PROJECT_NAME = "你的项目ID" compute = discovery.build('compute', 'v1') # 先获取项目私有镜像 resp = compute.images().list(project=PROJECT_NAME).execute() if "items" in resp: all_images.extend(resp["items"]) # 处理私有镜像的分页 while "nextPageToken" in resp: resp = compute.images().list( project=PROJECT_NAME, pageToken=resp["nextPageToken"] ).execute() if "items" in resp: all_images.extend(resp["items"]) # 再获取Debian官方公共镜像(示例) resp = compute.images().list(project='debian-cloud').execute() if "items" in resp: all_images.extend(resp["items"]) # 处理公共镜像的分页 while "nextPageToken" in resp: resp = compute.images().list( project='debian-cloud', pageToken=resp["nextPageToken"] ).execute() if "items" in resp: all_images.extend(resp["items"]) print(f"共获取到 {len(all_images)} 个镜像")
关于GCP Discovery API的分页
完全不用担心,GCP的Discovery API(包括Compute API)完全支持nextPageToken分页——只要你的资源数量超过单页返回上限(默认一般是100条,部分资源会有差异),响应里就会返回nextPageToken,用它请求下一页即可。你之前的核心问题就是没执行请求,还错误覆盖了资源列表。
内容的提问来源于stack exchange,提问作者OneRaynyDay
相关产品推荐
相关产品推荐

