这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段,并于 2023 年 6 月 1 日终止支持。
在 Python 中使用 AWS CDK
Python 是一种 AWS Cloud Development Kit (AWS CDK) 完全支持的且视为稳定的客户端语言。在 Python 中使用 AWS CDK 采用了熟悉的工具,包括标准 Python 实现(CPython)、带 virtualenv
的虚拟环境和 Python 包安装程序 pip
。通过 pypi.orgsnake_case
方法名称)。
您可以使用任何编辑器或 IDE。许多 AWS CDK 开发人员都使用 Visual Studio 代码
开始使用 Python
要使用 AWS CDK,您必须拥有 AWS 账户和凭证,并已安装 Node.js 和 AWS CDK Toolkit。请参阅 开始使用 AWS CDK。
Python AWS CDK 应用程序需要使用 Python 3.6 或更高版本。如果尚未安装,请在 python.orgyum
、apt
等)进行安装。Mac 用户可能会对 Homebrew
注意
第三方语言弃用:语言版本仅在供应商或社区共享其 EOL(生命周期终止)之前才受支持,如有更改,会另行通知。
还需要使用 Python 包安装程序 pip
和虚拟环境管理器 virtualenv
。在 Windows 上安装兼容的 Python 版本需要使用这些工具。在 Linux 上,pip
和 virtualenv
可以在软件包管理器中作为单独的软件包进行提供。或者,您可以使用以下命令进行安装:
python -m ensurepip --upgrade python -m pip install --upgrade pip python -m pip install --upgrade virtualenv
如果遇到权限错误,请运行带有 --user
标志的上述命令,以便将模块安装在您的用户目录中,或者使用 sudo
来获取在系统范围内安装模块的权限。
注意
Linux 发行版通常使用可执行文件名称 python3
表示 Python 3.x,使用 python
表示 Python 2.x 安装。有些发行版有一个可以安装的可选包,可让 python
命令表示 Python 3。如果失败,您可以通过在项目的主目录中编辑 cdk.json
来调整用于运行应用程序的命令。
注意
在 Windows 上,您可能需要使用 py 可执行文件(适用于 Windows 的 >Python 启动器
如果在命令行键入 python 后会显示一条关于从 Windows 应用商店安装 Python 的消息,即使安装了 Windows 版本的 Python,也请打开 Windows 的“管理应用程序执行别名”设置面板并关闭 Python 的两个应用程序安装程序条目。
创建项目
您可以通过在空目录中调用 cdk init
来创建一个新的 AWS CDK 项目。使用 --language
选项并指定 python
:
mkdir my-project cd my-project cdk init app --language python
cdk init
使用项目文件夹的名称来命名项目的各种元素,包括类、子文件夹和文件。文件夹名称中的连字符都将转换为下划线。但是,名称应遵循 Python 标识符的形式;例如,名称不应以数字开头,也不应包含空格。
要使用新项目,请激活其虚拟环境。这允许将项目的依赖项安装在本地项目文件夹中,而不是全局安装。
source .venv/bin/activate
注意
您可将其视为用于激活虚拟环境的 Mac/Linux 命令。Python 模板包含一个批处理文件 source.bat
,该文件允许在 Windows 上使用相同的命令。也可以使用传统的 Windows 命令 .\venv\Scripts\activate
。
如果您使用 CDK Toolkit v1.70.0 或更早版本来初始化 AWS CDK 项目,则您的虚拟环境位于 .env
目录中,而不是 .venv
。
重要
无论何时开始处理项目,都要激活该项目的虚拟环境。否则,您将无法访问安装在那里的模块,并且您安装的模块将进入 Python 全局模块目录(或将导致权限错误)。
首次激活虚拟环境后,请安装应用程序的标准依赖项:
python -m pip install -r requirements.txt
管理 AWS 构造库模块
使用 Python 软件包安装程序 pip 来安装和更新供您应用程序使用的 AWS 构造库模块以及您需要的其他软件包。pip 还会自动安装这些模块的依赖项。如果您的系统无法识别 pip 为独立命令,请将 pip 作为 Python 模块进行调用,如下所示:
python -m pip
PIP-COMMAND
大多数 AWS CDK 构造都在 aws-cdk-lib
中。实验性模块位于名称类似于 aws-cdk.
的单独模块中。服务名称包含 aws 前缀。如果您不确定某个模块的名称,请在 PyPI 上进行搜索SERVICE-NAME
.alpha
python -m pip install aws-cdk.aws-codestar-alpha
某些服务的构造位于多个命名空间中。例如,除 aws-cdk.aws-route53
之外,还有另外三个 Amazon Route 53 命名空间,aws-route53-targets
、aws-route53-patterns
和 aws-route53resolver
。
注意
CDK API Reference 的 Python 版本也显示了包名称。
用于将 AWS 构造库模块导入 Python 代码的名称如下所示。
import aws_cdk.aws_s3 as s3 import aws_cdk.aws_lambda as lambda_
在应用程序中导入 AWS CDK 类和 AWS 构造库模块时,我们建议采用以下做法。遵循这些准则将有助于让您的代码与其他 AWS CDK 应用程序保持一致并更易于理解。
-
通常,从顶层
aws_cdk
中导入单个类。from aws_cdk import App, Construct
-
如果您需要
aws_cdk
中的许多类,则可以使用cdk
的命名空间别名,而不是导入单个类。避免同时执行这两项操作。import aws_cdk as cdk
-
通常,使用短命名空间别名来导入 AWS 构造库。
import aws_cdk.aws_s3 as s3
安装模块后,请更新项目的 requirements.txt
文件,其中列出了项目的依赖项。最好手动执行此操作,而不是使用 pip freeze
。pip
freeze
会捕获 Python 虚拟环境中安装的所有模块的当前版本,这在将项目捆绑到其他地方运行时非常有用。
但是,通常情况下,您的 requirements.txt
应该只列出顶级依赖项(您的应用程序直接依赖的模块),而不会列出这些库的依赖项。这种策略让更新依赖项变得更加简单。
您可以编辑 requirements.txt
以允许升级;只需将版本号前面的 ==
替换为 ~=
即可升级到更高的兼容版本,或者完全删除版本要求以指定模块的最新可用版本。
适当编辑 requirements.txt
以允许升级后,可以随时发出以下命令来升级项目中已安装的模块:
pip install --upgrade -r requirements.txt
在 Python 中管理依赖项
在 Python 中,您可以在应用程序的 requirements.txt
或构造库的 setup.py
中输入依赖项来指定依赖项。然后使用 PIP 工具来管理依赖关系。通过以下方式之一来调用 PIP:
pip
command
options
python -m pipcommand
options
python -m pip 调用适用于大多数系统;pip 要求 PIP 的可执行文件位于系统路径上。如果 pip 不起作用,请尝试将其替换为 python -m pip。
cdk init --language python 命令会为您的新项目创建一个虚拟环境。这样每个项目就都有自己的依赖项版本,还有一个基本 requirements.txt
文件。每次开始使用项目时,都必须运行 source .venv/bin/activate 来激活此虚拟环境。在 Windows 上,改为运行 .\venv\Scripts\activate
CDK 应用程序
下面是一个 requirements.txt
示例文件。由于 PIP 不具备依赖锁定功能,我们建议您使用 == 运算符为所有依赖项指定确切的版本,如下所示。
aws-cdk-lib==2.14.0 aws-cdk.aws-appsync-alpha==2.10.0a0
使用 pip install 来安装模块不会自动将其添加到 requirements.txt
。必须自己动手添加。如果要升级到依赖项的更高版本,请在 requirements.txt
中编辑其版本号。
要在创建或编辑 requirements.txt
后安装或更新项目的依赖项,请运行以下命令:
python -m pip install -r requirements.txt
提示
pip freeze 命令以可写入文本文件的格式输出所有已安装依赖项的版本。这可以用作 pip install -r
的需求文件。此文件便于将所有依赖项(包括传递依赖项)固定到您测试过的确切版本。为避免以后升级软件包时出现问题,请为此使用单独的文件,例如 freeze.txt
(不是 requirements.txt
)。然后,在升级项目的依赖项时重新生成此文件。
第三方构造库
在库中,依赖项在 setup.py
中进行指定,以便应用程序使用包时会自动下载传递依赖项。否则,每个想要使用包的应用程序都需要将您的依赖项复制到其 requirements.txt
中。此处显示了一个示例 setup.py
。
from setuptools import setup setup( name='my-package', version='0.0.1', install_requires=[ 'aws-cdk-lib==2.14.0', ], ... )
要使用包进行开发,请创建或激活虚拟环境,然后运行以下命令。
python -m pip install -e .
尽管 PIP 会自动安装传递依赖项,但每个包只能安装一个副本。已选择依赖项树中指定的最高版本;应用程序对安装哪个版本的软件包始终拥有最终决定权。
Python 中的 AWS CDK 习语
语言冲突
在 Python 中,lambda
是一个语言关键字,因此不能将其用作 AWS Lambda 构造库模块或 Lambda 函数的名称。对于此类冲突,Python 的惯例是在变量名称中使用尾随下划线,如 lambda_
所示。
按照惯例,AWS CDK 构造的第二个参数名为 id
。在编写自己的堆栈和构造时,调用参数 id
会“掩盖”Python 内置函数 id()
,该函数用于返回对象的唯一标识符。此函数并不常用,但是如果您在构造中碰巧需要它,请重命名该参数,例如 construct_id
。
参数和属性
所有 AWS 构造库类都使用三个参数进行实例化:在其中定义构造的 scope(构造树中的父级)、id 和 props(构造用于配置其创建的资源的键/值对捆绑包)。其他类和方法也使用“属性捆绑包”模式作为参数。
scope 和 id 应始终作为位置参数而不是关键字参数进行传递,因为如果构造接受名为 scope 或 id 的属性,其名称就会改变。
在 Python 中,props 表示为关键字参数。如果参数包含嵌套数据结构,则使用在实例化时采用其自身关键字参数的类来表示这些结构。同样的模式也适用于采用结构化参数的其他方法调用。
例如,在 Amazon S3 存储桶的 add_lifecycle_rule
方法中,transitions
属性是 Transition
实例的列表。
bucket.add_lifecycle_rule( transitions=[ Transition( storage_class=StorageClass.GLACIER, transition_after=Duration.days(10) ) ] )
扩展某个类或重写某种方法时,您可能希望接受父类无法理解的其他参数,以满足自己的目的。在这种情况下,您应该使用 **kwargs
习语来接受您不在意的参数,并使用仅限关键字的参数来接受您感兴趣的参数。在调用父级的构造函数或重写的方法时,请仅传递所需的参数(通常只是 **kwargs
)。传递父类或方法不需要的参数会导致错误。
class MyConstruct(Construct): def __init__(self, id, *, MyProperty=42, **kwargs): super().__init__(self, id, **kwargs) # ...
AWS CDK 的未来版本可能会碰巧添加一个新属性,其名称与您用于自己属性的名称相同。这不会为您的构造或方法的用户带来任何技术问题(因为您的属性不会“向上沿链”传递,所以父类或重写的方法只会使用默认值),但可能会造成困惑。您可以对属性进行命名来避免这个潜在问题,这样它们就明确属于您的构造。如果有许多新属性,请将其捆绑到一个适当命名的类中,然后将其用作单个关键字参数进行传递。
缺失值
AWS CDK 使用 None
来表示缺失值或未定义的值。使用 **kwargs
时,如果未提供属性,则使用词典的 get()
方法提供默认值。避免使用 kwargs[...]
,因为这会引发缺失值的 KeyError
。
encrypted = kwargs.get("encrypted") # None if no property "encrypted" exists encrypted = kwargs.get("encrypted", False) # specify default of False if property is missing
某些 AWS CDK 方法(例如用于获取运行时上下文值的 tryGetContext()
)可能会返回 None
,您需要进行明确检查。
使用接口
Python 不像其他一些语言那样具有接口功能,不过其确实有类似的抽象基类
要表示一个类实现了特定的接口,可以使用 @jsii.implements
装饰器:
from aws_cdk import IAspect, IConstruct import jsii @jsii.implements(IAspect) class MyAspect(): def visit(self, node: IConstruct) -> None: print("Visited", node.node.path)
类型陷阱
Python 使用动态类型,其中所有变量都可以表示任何类型的值。参数和返回值可以用类型进行注释,但这些是“提示”,不会强制执行。这意味着在 Python 中,很容易将错误类型的值传递给 AWS CDK 构造。与静态类型语言不同,您不会在构建期间收到类型错误,而是在 JSII 层(在 Python 和 AWS CDK 的 TypeScript 核心之间进行转换)无法处理意外类型时收到运行时错误。
根据我们的经验,Python 程序员犯的类型错误往往属于以下类别。
-
在构造需要容器(Python 列表或词典)的地方传递单个值,反之亦然。
-
将与第 1 层 (
CfnXxxxxx
) 构造关联的类型的值传递给 L2 或 L3 构造,反之亦然。
AWS CDK Python 模块确实包含类型注释,因此您可以使用支持类型注释的工具来帮助处理类型。如果您使用的不是支持这些类型注释的 IDE,例如 PyCharm