- 后端
- 云原生
【免费下载链接】boto3
AWS SDK for Python (Boto3)
本文以 Resources reference 为骨架,逐层拆解 Boto3 面向对象资源层(
boto3.resources)的六大核心模块:资源模型(model)、请求参数(params)、响应处理器(response)、资源动作(action)、资源基类(base)与资源工厂(factory)。读完本文,你将掌握资源 JSON 定义如何被解析成ResourceModel、请求参数如何从标识符/数据成员/常量自动填充、低层 API 响应如何被转换为资源实例,以及boto3.resource('sqs')背后完整的对象生成链路。
一、资源层全景:参考文档在讲什么
docs/source/reference/core/resources.rst是 Boto3 文档集中 "Core References"(见 index.rst)下的 API 参考页,它通过 Sphinx 的automodule指令,将boto3.resources包中六个核心模块的公开类与函数全部纳入文档化范围:
| 参考文档中的小节 | 对应模块 | 文档化内容 |
|---|---|---|
| Resource model | boto3.resources.model | Identifier、Action、Parameter、Request、Waiter、ResponseResource、Collection、ResourceModel |
| Request parameters | boto3.resources.params | get_data_member、create_request_parameters、build_param_structure |
| Response handlers | boto3.resources.response | all_not_none、build_identifiers、build_empty_response、RawHandler、ResourceHandler |
| Resource actions | boto3.resources.action | ServiceAction、BatchAction、WaiterAction、CustomModeledAction |
| Resource base | boto3.resources.base | ResourceMeta、ServiceResource |
| Resource factory | boto3.resources.factory | ResourceFactory |
这一层是整个 Boto3 资源接口(面向对象 API,如sqs.Queue('url').receive_messages())的底层支撑。与之相对的是低层 Client 接口(如sqs_client.receive_message(...)),资源接口在 Client 之上提供了对象化、可组合的抽象。参考页本身是 API 索引,但其背后每个符号都在boto3/resources/目录中有完整实现,本文将结合源码与实际服务定义数据逐一展开。
二、Resource model:资源 JSON 定义的 Python 化抽象
boto3/resources/model.py的开篇注释说明了该模块的定位:将资源 JSON 描述格式抽象为一组 Python 对象,好处是接口 Pythonic(例如action.request.operation这样的属性链),且当 JSON 字段发生重命名等小改动时,消费方代码无需变更。这些模型同时被两类消费者使用:生成资源类的ResourceFactory,以及文档生成器。
2.1 核心模型类速览
模型层把一份resources-1.json拆解成以下对象:
Identifier:资源标识符,仅有name(标识符名称)与memberName(对应 shape 成员名,可选)两个属性。Action:一次服务操作动作,包含name、request(Request对象或None)、resource(ResponseResource对象或None)、path(JMESPath 搜索路径,可为None)。DefinitionWithParams:拥有params属性的基类,Request与Waiter都继承它。params属性会遍历 JSON 中的params列表,逐项构造Parameter(**item)。Parameter:自动填充的参数,核心字段是target(目标参数名,如QueueUrl)、source(来源类型)、name、path(JMESPath 查询)、value(常量值)。若 JSON 中出现未知字段,会通过logger.warning告警。Request:服务操作请求,在DefinitionWithParams基础上增加operation(低层服务操作名)。Waiter:等待器规格,常量PREFIX = 'WaitUntil',字段name与waiterName(底层等待器名称)。ResponseResource:动作执行后要创建的资源,字段type(资源类型名)与path(JMESPath 查询),并提供identifiers属性(解析为Parameter列表)与model属性(返回该类型的ResourceModel)。Collection:一组资源,继承Action,额外提供batch_actions属性,便捷访问其资源类型的批量动作。ResourceModel:一个资源的完整模型,包含标识符、属性、动作、子资源、引用与集合。
2.2 命名冲突处理:load_rename_map
资源模型可能遇到命名冲突:同一个名字可能同时是 shape 成员(属性)、动作、子资源、集合等。ResourceModel.load_rename_map定义了明确的优先级(从高到低):
- 加载动作(
resource.load) - 标识符(Identifiers)
- 动作(Actions)
- 子资源(Subresources)
- 引用(References)
- 集合(Collections)
- 等待器(Waiters)
- 属性(shape 成员)
_load_name_with_category在名字已被占用时为其追加类别后缀(如id冲突后变为id_action、id_collection、id_attribute),并维护_renamed字典;若追加后缀后仍冲突则直接抛出ValueError。注意meta是资源的保留名,任何类别都不能占用。批处理动作只暴露在集合上,因此不参与重命名;子资源使用大写驼峰命名,几乎只可能与其他子资源冲突。
2.3 服务资源的特殊处理:_get_has_definition
_get_has_definition有一个精巧设计:当模型名不在resource_defs中(即它是服务级资源,如sqs本身)时,服务资源会暴露该服务定义的所有资源作为子资源,使s3.Object('bucket-name', 'key')这类调用即使 JSON 中没有显式定义也能工作。对每个资源类型,它会检查是否在has关系里已有映射;若没有,则构造一个"伪造"的 has 定义,将所有标识符的source设为input,要求用户显式传入。
2.4 真实数据印证:SQS 资源定义
以 SQS 资源定义 为例:
service.actions.CreateQueue:请求操作为CreateQueue,响应资源为Queue,其标识符Url从响应QueueUrl字段(source: "response")取得。service.has.Queue:Queue子资源的Url标识符来源为input(用户传入)。service.hasMany.Queues:集合请求操作ListQueues,标识符Url从QueueUrls[]列表取(JMESPath 路径)。resources.Message:标识符为QueueUrl和ReceiptHandle(memberName指向 shape 成员);动作Delete的请求参数QueueUrl、ReceiptHandle均从资源标识符自动填充;batchActions.Delete使用Entries[*].Id(数据成员)与Entries[*].ReceiptHandle(标识符)构造批量删除参数。resources.Queue:load请求为GetQueueAttributes,参数AttributeNames[]是硬编码字符串常量All(source: "string"),path: "@"表示把整个响应作为资源数据。
这些定义展示了Parameter的四种source类型在真实数据中的完整用法:identifier、data、string/integer/boolean常量、input。
三、Request parameters:请求参数的自动填充管线
boto3/resources/params.py负责把资源模型中的参数定义转换成真实请求参数字典。核心链路是create_request_parameters→get_data_member/build_param_structure。
3.1 create_request_parameters:按来源取值的分发器
create_request_parameters(parent, request_model, params=None, index=None)遍历request_model.params,对每个Parameter按其source分发:
identifier:从父资源实例读取标识符属性,getattr(parent, xform_name(param.name))。data:通过get_data_member从父资源数据中按 JMESPath 查询取值(可能触发一次load)。string/integer/boolean:直接取定义中的常量value。input:由用户调用时传入,此处直接跳过。- 其他来源抛出
NotImplementedError。
函数支持传入既有params字典反复累加,这对批量动作中"反向 JMESPath 追加到列表"的场景尤其有用;index参数用于指定条目在列表中的位置。
3.2 get_data_member:延迟加载的数据访问
get_data_member(parent, path)先检查parent.meta.data是否为空;若为空且有load方法则先调用load(),否则抛出ResourceLoadException(提示"has no load method")。随后用jmespath.search(path, parent.meta.data)查询数据。这解释了资源属性的"懒加载"行为:首次访问属性时会自动发起一次load请求。
3.3 build_param_structure:反向 JMESPath
build_param_structure(params, target, value, index=None)是文档中自带 doctest 的精巧函数,实现"反向 JMESPath":从test[0]这类路径字符串构造嵌套对象。例如:
>>> build_param_structure(params, 'test[0]', 1) >>> print(params) {'test': [1]} >>> build_param_structure(params, 'foo.bar[0].baz', 'hello world') >>> print(params) {'test': [1], 'foo': {'bar': [{'baz': 'hello, world'}]}}实现上先用正则INDEX_RE = re.compile(r'\[(.*)\]$')检测[N]/[]/[*]三种索引形式,逐步在params中下钻(pos指针),数组项默认按字典占位填充,末尾项才真正写入值。SQS 定义中的Entries[*].Id、AttributeNames[]正是经由此函数展开成目标请求结构的。
四、Response handlers:把低层响应变成资源对象
boto3/resources/response.py负责把低层 Client 返回的原始响应字典转换为资源实例(或原样透传)。
4.1 build_identifiers:标识符值装配
build_identifiers(identifiers, parent, params=None, raw_response=None)按标识符定义逐项取值,source支持五种:
response:jmespath.search(identifier.path, raw_response),从低层响应中取。requestParameter:从请求参数params中按 JMESPath 取。identifier:从父资源取同名标识符。data:get_data_member从父资源数据取(可能触发加载)。input:用户传入,跳过。
返回值是按(xform_name(target), value)排序的元组列表。若值为列表,则代表响应是"复数"的(多资源)。
4.2 RawHandler 与 ResourceHandler:两种响应策略
RawHandler:仅做 JMESPath 搜索透传,若search_path存在且不等于'$',则jmespath.search(search_path, response),返回原始字典。适用于不产生新资源的动作(如queue.send_message返回原始响应)。ResourceHandler:从响应构造新资源。核心逻辑在__call__:- 通过
factory.load_from_definition加载目标资源类; - 若定义了
path,用 JMESPath 从原始响应中提取资源属性数据(存入meta.data); - 用
build_identifiers组装标识符字典; - 若任一标识符是列表,则响应为复数——以第一个列表的长度决定创建多少个实例,并逐项从列表头部消费(
value.pop(0)),非列表标识符对每个实例复用同一值; - 若所有标识符均非空,创建单个资源实例;
- 否则返回空值:若发生过远程调用,由
build_empty_response依据服务模型 shape 类型决定返回{}(structure)、[](list)或None。
- 通过
handle_response_item负责单个实例的构造,把父资源的低层 client 透传给新资源(kwargs['client'] = parent.meta.client),并将提取到的resource_data挂到resource.meta.data。
4.3 build_empty_response:按 shape 类型生成空值
build_empty_response(search_path, operation_name, service_model)从服务模型中取操作输出 shape,沿搜索路径逐段下钻(结构体取members[item],列表取member,遇到其他类型抛NotImplementedError),最后按type_name返回空结构体、空列表或None。这保证了"资源不存在"类场景下 API 返回值的类型一致性。
五、Resource actions:动作的三类执行器
boto3/resources/action.py定义了动作的可调用封装,它们被ResourceFactory挂到资源类上成为方法。
5.1 ServiceAction:单资源动作
ServiceAction构造时根据动作模型是否定义resource决定响应处理器:有则用ResourceHandler(构造新资源),无则用RawHandler。__call__的执行流程是:
- 将操作名转成 snake_case(
xform_name); - 调
create_request_parameters构建预填充参数,再params.update(kwargs)允许用户覆盖; - 从
parent.meta.client取对应低层操作并调用; - 交给响应处理器返回结果(原始字典或资源实例)。
对应到用户侧:sqs.get_queue_by_name(...)、s3.Bucket('foo').delete()都是ServiceAction。
5.2 BatchAction:集合批量动作
BatchAction继承ServiceAction,面向集合迭代器。其__call__遍历parent.pages()的每一页,对页内每个资源用create_request_parameters(..., params=params, index=index)累加参数,然后调用一次批量操作。文档注释中的典型场景是:一次删除多达 999 个 S3 对象,而不是逐个.delete()。若某一页参数为空则提前break,避免无意义的远程调用。返回值是每页低层响应字典组成的列表。SQS 的batchActions.Delete(DeleteMessageBatch)即走此路径。
5.3 WaiterAction:等待器动作
WaiterAction包装资源级等待器,如s3.Bucket('foo').wait_until_bucket_exists()。它从parent.meta.client.get_waiter(client_waiter_name)取得低层等待器,同样先create_request_parameters再wait(**params)。
5.4 CustomModeledAction:自定义注入动作
CustomModeledAction用于把自定义建模动作注入资源(例如 EC2 的delete_tags,对应 ec2/createtags.py 与 ec2/deletetags.py 的机制)。构造时接收动作名、JSON 定义、执行函数与事件发射器;inject时构造Action模型、生成动作文档串(ActionDocstring),并通过inject_attribute把函数挂到类属性上。
六、Resource base:资源的元数据与基类
boto3/resources/base.py提供ResourceMeta与ServiceResource。
6.1 ResourceMeta:资源元数据
ResourceMeta保存service_name(如's3')、identifiers(标识符名列表)、client(低层 Botocore 客户端)、data(已加载的资源属性数据)与resource_model。它实现了__repr__、__eq__(比较__dict__)与copy()。
6.2 ServiceResource:一切资源的基类
ServiceResource是所有资源的基类,其meta类属性在实例化时通过self.meta.copy()拷贝,避免影响同类其他实例。构造逻辑要点:
- 未显式传
client时自动boto3.client(self.meta.service_name); - 标识符既支持按定义顺序的位置参数(
for i, value in enumerate(args)),也支持关键字参数;未知关键字抛ValueError; - 构造后校验所有标识符均已设置,缺失抛
ValueError: Required parameter X not set; __eq__要求同类且所有标识符值相等;__hash__基于(类名, 标识符元组)。
因此s3.Object('bucket', 'key')缺key会直接抛异常,而两个s3.Bucket('same-name')实例相等。
七、Resource factory:从模型到类的代码生成器
boto3/resources/factory.py的ResourceFactory负责把ResourceModel变成真正的ServiceResource子类。load_from_definition的流程(与参考页"Resource factory"一节对应):
- 用 JSON 定义构造
ResourceModel; - 依据
shape从服务模型取 shape,调load_rename_map处理命名冲突; - 构造
ResourceMeta与类属性字典attrs; - 依次加载:标识符(
_load_identifiers)→ 动作(_load_actions,load与reload是特殊动作)→ 属性(_load_attributes)→ 集合(_load_collections)→ 引用与子资源(_load_has_relations)→ 等待器(_load_waiters); - 类名形如
s3.Bucket(服务资源命名为ServiceResource),基类为ServiceResource; - 若配置了事件发射器,发射
creating-resource-class.{cls_name}事件,允许注入自定义行为(CustomModeledAction即借此挂载); - 用
type()动态创建类。
各加载方法对应的属性形态:
- 标识符:
_create_identifier生成只读property,默认返回None而非抛AttributeError(便于实例化时给出更友好的校验错误)。 - 动作:
_create_action闭包共享ServiceAction;load特殊之处在于把响应写入self.meta.data,普通动作执行后则清空self.meta.data(下次访问属性时重新加载)。 - 属性:
_create_autoload_property生成懒加载property——meta.data为空时先load()(无load方法则抛ResourceLoadException),再返回meta.data.get(name)。 - 引用:
_create_reference懒求值,支持循环引用,needs_data标识符需要先加载数据。 - 子资源:
_create_class_partial类似functools.partial,把父实例的标识符值作为位置参数与低层 client 一起传给子资源类构造器,实现sqs.Queue('foo').Message('bar')这种链式创建。 - 集合:
_create_collection委托给CollectionFactory生成集合管理器属性。 - 等待器:
_create_waiter包装WaiterAction为do_waiter方法。 - 此外,工厂还会为每个资源注入
get_available_subresources(),返回排序后的子资源名列表。
八、结合使用:一次调用的完整数据流
把以上模块串起来,一次典型调用sqs.get_queue_by_name(QueueName='myqueue')的完整链路是:
sqs服务资源类由ResourceFactory.load_from_definition依据 SQS 资源定义 生成;get_queue_by_name动作模型解析自service.actions.GetQueueByName:请求操作GetQueueUrl,响应资源Queue;ServiceAction.__call__调create_request_parameters预填充参数(此处用户通过QueueName传入),再调parent.meta.client.get_queue_url(...);- 响应交给
ResourceHandler:build_identifiers从响应QueueUrl字段取出Url标识符,load_from_definition生成Queue类并实例化,path定义的数据挂到meta.data; - 用户后续访问
queue.attributes等属性时,_create_autoload_property检测meta.data为空则触发GetQueueAttributes的load动作,将结果缓存于meta.data。
这一流程同时被tests/unit/docs/test_action.py、test_factory.py等单元测试(见 tests/unit/docs)和 guide/resources.rst 的用户指南所验证。
九、延伸阅读与注意事项
- 用户视角的完整教程见 Resources 指南,其中覆盖标识符、属性、动作、引用、子资源、集合与等待器的使用方法与代码示例。
- 各服务的实际资源定义 JSON 位于 boto3/data 下,例如 S3 的 resources-1.json、EC2 的多版本定义,可对照本文模型层理解字段语义。
- 参考页 Resources reference 本身由 Sphinx
automodule自动抽取各模块 docstring 生成,与本文对应的源码文件model.py、params.py、response.py、action.py、base.py、factory.py是权威的 API 细节来源。 - 值得留意的是,资源接口面向对象抽象自 Botocore Client;若需要使用较新的服务功能,官方指南建议直接使用 Client 接口(资源接口在 Boto3 生命周期内保持兼容但不再增加新特性,见 resources.rst 开篇说明)。
- 后端
- 云原生
【免费下载链接】boto3
AWS SDK for Python (Boto3)
相关推荐
Redux 核心 API 完全参考:从 createStore 到 Store 方法的源码级解读
Redux 核心 API 完全参考:从 createStore 到 Store 方法的源码级解读 本篇指南以本仓库 docs/api 下的 API Refere
前端Boto3 资源接口(Resources)完全指南:从 Session 到对象的 AWS 高级抽象
Boto3 资源接口(Resources)完全指南:从 Session 到对象的 AWS 高级抽象 Boto3 的 Resources 接口为 AWS 提供了一
后端云原生Salt 编排核心:salt.state 状态选项完整参考与源码级解析
Salt 编排核心:salt.state 状态选项完整参考与源码级解析 导读 本文以 Salt 仓库中 Orchestrate Runner 文档 https:
运维配置管理后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考