使用discovery方法获取GCP磁盘详情时代码挂起如何排查
问题场景
使用Python调用GCP SDK接口查询磁盘资源时出现执行异常,相关复现代码如下:
from google.oauth2 import service_account from googleapiclient import discovery def main(): cred = service_account.Credentials.from_service_account_file("json file path") service = discovery.build("compute", "v1", credentials=cred) request = service.disks().list(project="projectid", zone="us-central1-a") print(request) while request is not None: response = request.execute() print(response) for disk in response["items"]: # TODO: Change code below to process each `disk` resource: print(disk) request = service.disks().list_next( previous_request=request, previous_response=response ) if __name__ == "__main__": main()
异常表现
代码运行后可成功执行print(request)语句打印请求对象,之后无任何输出、无报错信息,执行流程卡在while循环阶段持续挂起无返回;当前账号对应的GCP项目中已创建存在磁盘资源,无法正常拉取磁盘列表详情。
问题根因
- 核心代码缩进错误:分页迭代的
list_next调用、响应打印、磁盘资源遍历逻辑全部写在了while循环外部。循环内部仅会重复执行第一次构造的request.execute()请求,永远不会更新request变量触发循环退出条件,也永远不会执行后续的结果处理逻辑,直接导致进程卡在循环中反复发起请求。 - 缺少超时配置:构建compute服务客户端时未设置请求超时,若遇到网络波动、API连通性异常,请求会无限等待不会抛出超时错误,表现为进程无响应挂起。
- 未做兼容判空:直接读取
response["items"],若对应区域下无磁盘资源会直接触发KeyError,原代码因逻辑未走到该步骤暂未触发该问题。
修复方案
调整代码逻辑缩进,将响应处理、分页更新逻辑移入while循环内部,补充超时配置和空值兼容,修复后可运行代码如下:
from google.oauth2 import service_account from googleapiclient import discovery def main(): # 替换为实际的服务账号密钥文件路径 cred = service_account.Credentials.from_service_account_file( "service_account.json", scopes=["https://www.googleapis.com/auth/cloud-platform"] ) # 增加cache_discovery=False避免发现文档缓存异常,配置重试次数 service = discovery.build( "compute", "v1", credentials=cred, cache_discovery=False, num_retries=3 ) request = service.disks().list(project="替换为实际项目ID", zone="us-central1-a") while request is not None: # 单次请求设置超时时间,避免无限挂起 response = request.execute(num_retries=2, timeout=30) # 空值兼容,无磁盘资源时返回空列表不报错 for disk in response.get("items", []): # 自定义磁盘资源处理逻辑 print(f"磁盘名称: {disk['name']}, 容量: {disk['sizeGb']}GB, 类型: {disk['type'].split('/')[-1]}") # 循环内更新下一页请求对象,无下一页时request为None自动退出循环 request = service.disks().list_next( previous_request=request, previous_response=response ) if __name__ == "__main__": main()
额外排查点
- 确认使用的服务账号已被授予
compute.disks.list相关权限(如Compute Viewer角色),权限不足时会抛出对应权限错误,不会无响应挂起 - 确认运行环境网络可正常连通GCP Compute Engine API端点,若处于受限网络环境需提前配置系统级或代码级代理
- 替换代码中占位的密钥路径、项目ID为实际业务值,确认填写的zone区域和实际磁盘所在区域一致
内容的提问来源于stack exchange,提问作者Jr Dna
相关产品推荐
相关产品推荐

