ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

google-api-python-client 批量请求(Batch)完全指南:合并 HTTP 调用、回调与 1000 上限详解

google-api-python-client 批量请求(Batch)完全指南:合并 HTTP 调用、回调与 1000 上限详解 后端【免费下载链接】google-api-python-client The official Python client library for Googles discovery based APIs.项目地址https://gitcode.com/gh_mirrors/go/google-api-python-client点击查看免费下载本文以官方指南 docs/batch.md 为主体结合 googleapiclient/http.py 源码与 tests/test_http.py、tests/test_discovery.py 测试用例系统讲解 google-api-python-client 的批量请求Batch机制。读完本文你将掌握如何用new_batch_http_request()把多个 API 调用合并为单个 HTTP 请求、如何利用全局/局部回调处理响应与异常、如何正确使用request_id以及理解 1000 次调用上限和媒体上传禁用等约束的底层原因。为什么需要批量请求每次你的应用发起一个 HTTP 连接都会产生一定的额外开销连接建立、TLS 握手、请求/响应头传输等。google-api-python-client 官方支持batching批量请求允许你把多个 API 调用打包进一个HTTP 请求中从而显著降低网络往返次数。官方文档 docs/batch.md 给出了两个典型场景大量小请求你有很多体积小、数量多的请求要发出希望最小化 HTTP 请求开销例如批量读取多个资源离线数据同步用户在你的应用离线期间修改了数据应用恢复联网后需要把本地数据与服务器同步一次发送大量 update 和 delete 操作。在这类场景下逐个调用.execute()会让每个调用都独立走一次完整 HTTP 往返而批量请求只需一次往返即可完成全部调用。两条硬性限制务必牢记官方文档明确了两条批量请求的使用限制源码层面也做了强制校验单个批次最多 1000 次调用超过 1000 次必须拆分为多个批次请求。该限制在 googleapiclient/http.py 中定义为常量MAX_BATCH_LIMIT 1000并在add()方法中强制执行——当len(self._order) MAX_BATCH_LIMIT时会抛出BatchError见 http.py。测试用例 tests/test_http.pytest_add_fail_for_over_limit正是循环添加 1000 个请求后再尝试添加第 1001 个验证会抛出BatchError。批量请求中不能使用媒体上传media upload对象这源于add()内部的校验逻辑——if request.resumable is not None: raise BatchError(Media requests cannot be used in a batch request.)见 http.py。对应测试test_add_fail_for_resumabletests/test_http.py先给请求挂上MediaFileUpload(..., resumableTrue)再验证batch.add()抛出BatchError。关于媒体上传的具体用法可参考 docs/media.md。基本用法三步完成一次批量请求创建批量请求的流程非常简单官方文档给出的步骤是在 service 对象上调用new_batch_http_request()得到一个BatchHttpRequest对象对每个要执行的请求调用add()加入批次可附带回调调用execute()真正发起请求——该方法是阻塞的会一直执行到所有回调都被调用完毕。示例一多个读请求 每个请求各自的回调这是官方文档 docs/batch.md 中的第一个完整示例两个 API 请求被打包进一个 HTTP 请求并各自配备回调def list_animals(request_id, response, exception): if exception is not None: # Do something with the exception pass else: # Do something with the response pass def list_farmers(request_id, response): Do something with the farmers list response. pass service build(farm, v2) batch service.new_batch_http_request() batch.add(service.animals().list(), callbacklist_animals) batch.add(service.farmers().list(), callbacklist_farmers) batch.execute()注意list_farmers只声明了(request_id, response)两个参数即使回调签名里省略了exception参数也不会报错——因为 Python 允许回调签名比实际传入参数少源码在 http.py 中始终以callback(request_id, response, exception)三个位置参数调用回调。示例二多个写请求 一个全局回调new_batch_http_request()也可以直接传入一个全局回调它会对批次中的每个响应都调用一次。官方文档第二个示例演示了用全局回调处理三次插入操作def insert_animal(request_id, response, exception): if exception is not None: # Do something with the exception pass else: # Do something with the response pass service build(farm, v2) batch service.new_batch_http_request(callbackinsert_animal) batch.add(service.animals().insert(namesheep)) batch.add(service.animals().insert(namepig)) batch.add(service.animals().insert(namellama)) batch.execute()全局回调与局部回调可以并存官方文档特别说明如果你同时在new_batch_http_request()和add()上都提供了回调那么两个回调都会被调用。从源码结构可以确认这一点http.py 将全局回调保存在self._callback而 add() 把每个请求的局部回调保存在self._callbacks[request_id]在execute()的回调处理循环http.py中先调用局部回调再调用全局回调。测试test_execute_global_callbacktests/test_http.py验证了仅传入全局回调时批次内所有响应都会触发该回调。回调签名与 request_id 机制回调函数的三个参数含义与官方文档及 http.py 的 docstring 一致参数含义request_id每个 API 调用对应的唯一请求标识符由库自动生成或由你通过add(request_id...)显式提供原样传给回调response反序列化后的 API 调用响应对象若调用出错则为Noneexceptiongoogleapiclient.errors.HttpError异常对象当该调用返回 HTTP 错误时被设置无错误时为Nonerequest_id 的自定义与唯一性约束add()方法允许通过request_id参数为每个请求指定 ID见官方文档及 http.py 的 docstring不传 request_id库会自动生成。_new_id()http.py采用自动递增计数并跳过已占用的 ID自定义 request_id必须保证唯一。若重复add()会抛出KeyError: A request with this ID already exists: ...http.py。对应测试 tests/test_http.py 先add(self.request1, request_id1)再重复添加断言抛出KeyError文档建议要么全部自定义、要么全部不传避免混用引发冲突。在批次内部request_id会经过 URL 编码后写入每个子请求的Content-ID头_id_to_headerhttp.py响应返回时再通过_header_to_id反向解析http.py从而把响应与原始请求一一对应。深入源码BatchHttpRequest 内部是如何工作的BatchHttpRequest类定义在 googleapiclient/http.pydocstring 中附有与官方文档一致的最小可运行示例。理解它的内部结构能帮你更好地预判行为与排查问题。创建new_batch_http_request() 由 discovery 动态生成service.new_batch_http_request()并不是手写的固定方法而是Resource._add_basic_methods()在构建服务对象时基于发现文档discovery document动态生成的discovery.pybatch_uri %s%s % ( rootDesc[rootUrl], rootDesc.get(batchPath, batch), ) def new_batch_http_request(callbackNone): return BatchHttpRequest(callbackcallback, batch_uribatch_uri)也就是说批量请求的提交地址batch URI由服务的rootUrl与发现文档中的batchPath拼接而成。测试 tests/test_discovery.py 对此有直接验证zoo 服务在发现文档中定义了batchPath生成的_batch_uri为https://www.googleapis.com/batchZooplus 服务未定义batchPath则回退到默认值https://www.googleapis.com/batch。而直接手动构造BatchHttpRequest()不带batch_uri时会使用遗留默认端点_LEGACY_BATCH_URI https://www.googleapis.com/batchhttp.py并打印一条警告日志提示该遗留端点即将停用、建议改用service.new_batch_http_request()http.py。因此强烈建议始终通过服务对象创建批次让库自动选择正确的 API 专属端点。发送子请求被序列化为 MIME multipart/mixed 消息execute()http.py最终调用_execute()http.py其核心步骤包括用MIMEMultipart(mixed)构造外层消息每个子请求封装为一个MIMENonMultipart(application, http)部分设置Content-Transfer-Encoding: binary与基于request_id的Content-ID头通过_serialize_request()http.py把每个HttpRequest转换为application/http格式的字符串包含状态行、请求头与请求体写入各自的分区以content-type: multipart/mixed; boundary...的头部对self._batch_uri发起一次POST请求响应用FeedParser解析回 multipart 消息逐个分区反序列化存入self._responses[request_id]。容错401 自动刷新凭据并重发execute()中有一段值得注意的容错逻辑http.py批次返回后会遍历所有响应凡是状态码为401的子请求都会调用_refresh_and_apply_credentials()刷新其凭据同一凭据对象在整个批次中只刷新一次见 http.py然后把这些 401 的子请求单独组成一个新批次重新发送。测试test_http_errors_passed_to_callbacktests/test_http.py验证了 401 子请求会触发凭据刷新并重试且HttpMockSequence中准备了两次BATCH_RESPONSE_WITH_401响应供两轮发送使用。错误处理HttpError 通过 exception 参数传给回调execute()对每个子请求的处理逻辑是http.py若响应状态 300构造HttpError否则用request.postproc(resp, content)反序列化出响应对象。HttpError会被捕获并作为回调的exception参数传入而不会中断整个批次。测试test_execute_batch_http_errortests/test_http.py验证批次中一个请求成功{foo: 42}另一个返回 403Access Not Configured后者通过callbacks.exceptions[2]拿到完整的HttpError字符串。与之配套的异常类型BatchError定义于 googleapiclient/errors.py用于表示批次操作层面的错误如超限、媒体请求混入、响应格式不正确等。在真实项目中继续深入若想理解批次之外的单请求执行细节URI 过长时 GET 转 POST 等行为可查看 googleapiclient/http.py 中的HttpRequest类http.py 起媒体上传、下载与批量请求的关系可参考 docs/media.md分页、认证等其他指南位于 docs/ 目录下如 docs/oauth.md、docs/pagination.md完整的批量请求行为契约可在 tests/test_http.py含test_execute_empty_batch_no_http、超限、resumable 拒绝、401 重试、全局回调、HTTP 错误透传等用例与 tests/test_discovery.pybatchPath 端点推导中找到对应验证。小结批量请求是 google-api-python-client 降低 HTTP 开销、提升吞吐的重要能力。使用时牢记三条核心规则单个批次不超过 1000 个调用、禁止混入媒体上传请求、通过service.new_batch_http_request()而非直接构造BatchHttpRequest来获取正确的 API 专属端点。配合回调机制全局 局部可并存与request_id唯一性管理你可以在一次网络往返内可靠地完成大量小型读/写操作并获得逐请求的细粒度错误处理能力。赞分享后端【免费下载链接】google-api-python-client The official Python client library for Googles discovery based APIs.项目地址https://gitcode.com/gh_mirrors/go/google-api-python-client点击查看免费下载相关推荐WSABuilds 安装指南在 Windows 10/11 上快速跑起安卓和 Google Play 的完整流程WSABuilds 安装指南在 Windows 10/11 上快速跑起安卓和 Google Play 的完整流程 WSABuilds 把 Windows 运行开发工具JSONWebToken.swift高级用法自定义声明集和头部参数配置指南JSONWebToken.swift高级用法自定义声明集和头部参数配置指南 JSONWebToken.swift是一个强大的Swift实现的JSON Web终极Laravel日志查看器如何快速优雅地管理你的应用日志终极Laravel日志查看器如何快速优雅地管理你的应用日志 你是否还在为查看Laravel应用日志而烦恼还在原始文本文件中苦苦搜索关键信息吗Log Vie后端日志分析开发工具上一篇打造专业简历的10个排版秘诀极简风格CV的行高、字重与可读性优化指南下一篇用 ProcessHacker 排查系统卡顿CPU、内存、磁盘硬件监控完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表