Utilización del AWS CDK en Python - AWS Cloud Development Kit (AWS CDK) v2

Esta es la segunda versión de la Guía para desarrolladores de AWS CDK. La primera versión del CDK pasó a la etapa de mantenimiento el 1.° de junio de 2022 y no cuenta con soporte desde el 1.° de junio de 2023.

Utilización del AWS CDK en Python

Python es un lenguaje de cliente totalmente compatible con AWS Cloud Development Kit (AWS CDK) y se lo considera estable. Para trabajar con AWS CDK en Python se utilizan herramientas conocidas, como la implementación estándar de Python (CPython), los entornos virtuales con virtualenv y el instalador pip de paquetes de Python. Los módulos que componen la Biblioteca de constructos de AWS se distribuyen a través de pypi.org. La versión Python del evento AWS CDK usa identificadores al estilo de Python (por ejemplo, nombres de métodos snake_case).

Puede usar cualquier editor o IDE. Muchos desarrolladores de AWS CDK usan Visual Studio Code (o su equivalente de código abierto VSCodium), que tiene buena compatibilidad con Python a través de una extensión oficial. El editor IDLE incluido con Python será suficiente para empezar. Los módulos de Python para AWS CDK tienen sugerencias de tipos, que son útiles para una herramienta de lint o un IDE que admita la validación de tipos.

Introducción a Python

Para trabajar con el AWS CDK, debe tener una cuenta de AWS y credenciales, y haber instalado Node.js y el kit de herramientas de AWS CDK. Consulte Introducción al AWS CDK.

Las aplicaciones de AWS CDK de Python requieren Python 3.6 o posterior. Si aún no lo tiene instalado, descargue una versión compatible para su sistema operativo en python.org. Si utiliza Linux, es posible que su sistema tenga una versión compatible, o puede instalarlo mediante el administrador de paquetes de distribución (yum, apt, etc.). Los usuarios de Mac pueden estar interesados en Homebrew, un administrador de paquetes estilo Linux para macOS.

nota

Obsolescencia del lenguaje de terceros: la versión en otros idiomas solo se admite hasta que el proveedor o la comunidad compartan su fecha de caducidad (EOL) y está sujeta a cambios con previo aviso.

También se requieren el instalador del paquete Python, pip, y el administrador del entorno virtual, virtualenv. Las instalaciones de Windows de las versiones de Python compatibles incluyen estas herramientas. En Linux, pip y virtualenv se pueden proporcionar como paquetes separados en el administrador de paquetes. Como alternativa, también puede instalarlos con los siguientes comandos:

python -m ensurepip --upgrade python -m pip install --upgrade pip python -m pip install --upgrade virtualenv

Si se produce un error de permisos, ejecute los comandos anteriores con la marca --user para que los módulos se instalen en su directorio de usuarios o utilice sudo para obtener los permisos necesarios para instalar los módulos en todo el sistema.

nota

Es común que las distribuciones de Linux usen el nombre ejecutable python3 para Python 3.x y hagan referencia python a una instalación de Python 2.x. Algunas distribuciones tienen un paquete opcional que puede instalar y que hace que el comando python haga referencia a Python 3. Si esto no funciona, puede ajustar el comando utilizado para ejecutar la aplicación editando cdk.json en el directorio principal del proyecto.

nota

En Windows, es posible que desee invocar Python (y pip) mediante el ejecutable py, el lanzador >Python para Windows. Entre otras cosas, el lanzador permite especificar fácilmente qué versión instalada de Python desea usar.

Si cuando escribe python en la línea de comandos aparece un mensaje sobre la instalación de Python desde la Tienda Windows, incluso después de instalar una versión de Python para Windows, abra el panel de configuración Administrar alias de ejecución de aplicaciones de Windows y desactive las dos entradas del instalador de aplicaciones para Python.

Creación de un proyecto

Cree un nuevo proyecto AWS CDK, mediante la invocación de cdk init en un directorio vacío. Utilice la opción --language y especifique python:

$ mkdir my-project $ cd my-project $ cdk init app --language python

cdk init utiliza el nombre de la carpeta del proyecto para asignar un nombre a varios elementos del proyecto, incluidas las clases, las subcarpetas y los archivos. Los guiones del nombre de la carpeta se convierten en guiones bajos. Aunque, de lo contrario, el nombre debe seguir la forma de un identificador de Python; por ejemplo, no debe comenzar por un número ni contener espacios.

Para trabajar con el nuevo proyecto, active su entorno virtual. Esto permite que las dependencias del proyecto se instalen localmente en la carpeta del proyecto, en lugar de hacerlo globalmente.

$ source .venv/bin/activate
nota

Es posible que reconozca esto como el comando de Mac/Linux para activar un entorno virtual. Las plantillas de Python incluyen un archivo por lotes, source.bat, que permite utilizar el mismo comando en Windows. El comando tradicional de Windows .\venv\Scripts\activate también funciona.

Si inicializó su proyecto de AWS CDK con el Toolkit v1.70.0 o anterior, su entorno virtual se encuentra en el directorio .env en lugar de .venv.

importante

Active el entorno virtual del proyecto cada vez que empiece a trabajar en él. De lo contrario, no tendrá acceso a los módulos instalados allí y los módulos que instale irán al directorio global de módulos de Python (o generarán un error de permiso).

Tras activar su entorno virtual por primera vez, instale las dependencias estándar de la aplicación:

$ python -m pip install -r requirements.txt

Administración de los módulos de la biblioteca de constructo AWS

Use el instalador de paquetes de Python, pip, para instalar y actualizar los módulos de la biblioteca de constructos de AWS para que los usen sus aplicaciones, así como otros paquetes que necesite. pip también instala las dependencias de esos módulos automáticamente. Si su sistema no reconoce pip como un comando independiente, invoque pip como un módulo de Python, de la siguiente manera:

$ python -m pip <PIP-COMMAND>

La mayoría de los constructos de AWS CDK están incluidos en aws-cdk-lib. Los módulos experimentales están en módulos separados denominados aws-cdk.<SERVICE-NAME>.alpha. El nombre del servicio incluye un prefijo aws. Si no está seguro del nombre de un módulo, búsquelo en PyPI. Por ejemplo, el siguiente comando instala la biblioteca CodeStar de AWS.

$ python -m pip install aws-cdk.aws-codestar-alpha

Los constructos de algunos servicios están en más de un espacio de nombres. Por ejemplo, además de aws-cdk.aws-route53, hay tres espacios de nombres adicionales de Amazon Route 53: denominados aws-route53-targets, aws-route53-patterns y aws-route53resolver.

nota

La edición de Python de la referencia de la API de CDK también muestra los nombres de los paquetes.

Los nombres utilizados para importar los módulos de la biblioteca de constructos de AWS al código de Python son los siguientes.

import aws_cdk.aws_s3 as s3 import aws_cdk.aws_lambda as lambda_

Recomendamos las siguientes prácticas al importar clases de AWS CDK y módulos de la Biblioteca de constructos de AWS a sus aplicaciones. Seguir estas directrices ayudará a que su código sea coherente con el de otras aplicaciones de AWS CDK y a que sea más fácil de entender.

  • En general, importe clases individuales del nivel superior de aws_cdk.

    from aws_cdk import App, Construct
  • Si necesita muchas clases de aws_cdk, puede utilizar un alias de espacio de nombres de cdk en lugar de importar clases individuales. Evite hacer ambas cosas.

    import aws_cdk as cdk
  • Por lo general, se importan las Bibliotecas de constructos de AWS por medio del alias de espacio de nombres cortos.

    import aws_cdk.aws_s3 as s3

Después de instalar un módulo, actualice el archivo requirements.txt del proyecto, que contiene una lista de las dependencias del proyecto. Es mejor hacerlo manualmente en lugar de usar pip freeze. pip freeze captura las versiones actuales de todos los módulos instalados en el entorno virtual de Python, lo que puede resultar útil cuando se agrupa un proyecto para ejecutarlo en otro lugar.

Sin embargo, normalmente el requirements.txt debe enumerar solo las dependencias de nivel superior (los módulos de los que depende directamente la aplicación) y no las dependencias de esas bibliotecas. Esta estrategia simplifica la actualización de las dependencias.

Puede editar requirements.txt para permitir las actualizaciones; basta con sustituir == a un número de versión anterior con ~= para que permita actualizar a una versión compatible superior o eliminar por completo el requisito de versión para especificar la última versión disponible del módulo.

Si requirements.txt se editó adecuadamente para permitir las actualizaciones, ejecute este comando para actualizar los módulos instalados del proyecto en cualquier momento:

$ pip install --upgrade -r requirements.txt

Administración de dependencias en Python

En Python, las dependencias se especifican colocándolas en requirements.txt para aplicaciones o setup.py para bibliotecas de constructos. Luego, las dependencias se administran con la herramienta PIP. El PIP se invoca de una de las siguientes formas:

pip <command options> python -m pip <command options>

La invocación python -m pip funciona en la mayoría de los sistemas; pip requiere que el ejecutable de PIP esté en la ruta del sistema. Si pip no funciona, intente sustituirlo por python -m pip.

El comando cdk init --language python crea un entorno virtual para su nuevo proyecto. Esto permite que cada proyecto tenga sus propias versiones de las dependencias y también un archivo requirements.txt básico. Debe activar este entorno virtual. Para ello, ejecute source .venv/bin/activate cada vez que comience a trabajar en el proyecto. En Windows, ejecute .\venv\Scripts\activate en su lugar.

Aplicaciones CDK

A continuación se muestra un ejemplo de un archivo requirements.txt. Como PIP no tiene una característica de bloqueo de dependencias, recomendamos que utilice el operador == para especificar las versiones exactas de todas las dependencias, como se muestra aquí.

aws-cdk-lib==2.14.0 aws-cdk.aws-appsync-alpha==2.10.0a0

Cuando instala un módulo mediante pip install, este no se agrega automáticamente a requirements.txt. Debe hacerlo usted mismo. Si desea actualizar a una versión posterior de una dependencia, edite su número de versión en requirements.txt.

Para instalar o actualizar las dependencias del proyecto después de crear o editar requirements.txt, ejecute lo siguiente:

python -m pip install -r requirements.txt
sugerencia

El comando pip freeze muestra las versiones de todas las dependencias instaladas en un formato que se puede escribir en un archivo de texto. Se puede utilizar como un archivo de requisitos con pip install -r. Este archivo es práctico para fijar todas las dependencias (incluidas las transitivas) a las versiones exactas con las que llevó a cabo las pruebas. Para evitar problemas cuando actualice los paquetes más adelante, utilice un archivo independiente para ello, como freeze.txt (no requirements.txt). A continuación, regenérelo cuando actualice las dependencias del proyecto.

Bibliotecas de constructos de terceros

En las bibliotecas, las dependencias se especifican en setup.py, de modo que las dependencias transitivas se descargan automáticamente cuando una aplicación utiliza el paquete. De lo contrario, todas las aplicaciones que quieran usar su paquete deberán copiar sus dependencias en su requirements.txt. A continuación, se muestra un ejemplo de setup.py.

from setuptools import setup setup( name='my-package', version='0.0.1', install_requires=[ 'aws-cdk-lib==2.14.0', ], ... )

Para trabajar en el paquete de desarrollo, cree o active un entorno virtual y, a continuación, ejecute el siguiente comando.

python -m pip install -e .

Aunque PIP instala automáticamente las dependencias transitivas, solo puede haber una copia instalada de cada paquete. Se selecciona la versión que se especifique más arriba en el árbol de dependencias; las aplicaciones siempre tienen la última palabra sobre qué versión de los paquetes se instalan.

Expresiones idiomáticas de AWS CDK en Python

Conflictos entre lenguajes

En Python, lambda es una palabra clave del lenguaje, por lo que no se puede utilizar como nombre para el módulo de la Biblioteca de constructos de AWS Lambda o para las funciones de Lambda. La convención de Python para este tipo de conflictos es usar un guion bajo al final, como en el nombre de la variable lambda_.

Por convención, el segundo argumento de los constructos de AWS CDK se denomina id. Cuando escribe sus propias pilas y constructos, llamar a un parámetro id “sombras” la función integrada de Python id(), que devuelve el identificador único de un objeto. Esta función no se usa con mucha frecuencia, pero si la necesita en el constructo, cambie el nombre del argumento, por ejemplo construct_id.

Argumentos y propiedades

Se crean las instancias de todas las clases de la Biblioteca de constructos de AWS con tres argumentos: el ámbito en el que se define el constructo (su elemento principal en el árbol de constructos), un id y props, un conjunto de pares clave/valor que el constructo utiliza para configurar los recursos que crea. Otras clases y métodos también utilizan el patrón de “agrupación de atributos” como argumento.

scope e id siempre deben pasarse como argumentos posicionales, no como argumentos de palabras clave, ya que sus nombres cambian si el constructo acepta una propiedad denominada scope o id.

En Python, los props se expresan como argumentos de palabras clave. Si un argumento contiene estructuras de datos anidadas, estas se expresan mediante una clase que toma sus propios argumentos de palabras clave en la instanciación. El mismo patrón se aplica a otras llamadas de métodos que utilizan un argumento estructurado.

Por ejemplo, en el método add_lifecycle_rule de un bucket de Amazon S3, la propiedad transitions es una lista de instancias Transition.

bucket.add_lifecycle_rule( transitions=[ Transition( storage_class=StorageClass.GLACIER, transition_after=Duration.days(10) ) ] )

Cuando amplíe una clase o anule un método, es posible que desee aceptar argumentos adicionales para sus propios fines que la clase principal no comprenda. En este caso, debe aceptar los argumentos que no tenga problema en usar en la expresión idiomática **kwargs y usar argumentos que solo contengan palabras clave para aceptar los argumentos que sean de su interés. Cuando llame al constructo del método principal o al anulado, pase solo los argumentos que espera (normalmente solo **kwargs). Si se pasan argumentos que la clase o el método principal no esperan, se produce un error.

class MyConstruct(Construct): def __init__(self, id, *, MyProperty=42, **kwargs): super().__init__(self, id, **kwargs) # ...

Una futura versión del AWS CDK podría agregar casualmente una nueva propiedad con el nombre que utilizó para su propiedad. Esto no provocará ningún problema técnico a los usuarios de su constructo o método (dado que su propiedad no pasa a un nivel superior de la cadena, la clase principal o el método anulado simplemente utilizarán un valor predeterminado), pero puede provocar confusión. Puede evitar este posible problema asignando un nombre a sus propiedades de forma que pertenezcan claramente a su constructo. Si hay muchas propiedades nuevas, agrúpelas en una clase con el nombre adecuado y pásela como un único argumento de palabra clave.

Valores faltantes

AWS CDK utiliza None para representar valores faltantes o indefinidos. Cuando trabaje con **kwargs, utilice el método get() del diccionario para proporcionar un valor predeterminado si no se proporciona una propiedad. Evite usar kwargs[…​], ya que esto aumenta los KeyError para los valores faltantes.

encrypted = kwargs.get("encrypted") # None if no property "encrypted" exists encrypted = kwargs.get("encrypted", False) # specify default of False if property is missing

Es posible que algunos métodos de AWS CDK (como tryGetContext() para obtener un valor de contexto en tiempo de ejecución) devuelvan None, lo que deberá comprobar de forma explícita.

Uso de una interfaz

Python no tiene una característica de interfaz como la tienen otros lenguajes, aunque sí tiene clases base abstractas, que son similares. (Si no está familiarizado con las interfaces, en Wikipedia hay una buena introducción a estos). TypeScript, el lenguaje en el que se implementa AWS CDK, se proporciona interfaces, y constructos y otros objetos de AWS CDK a menudo requieren un objeto que se adhiera a una interfaz en particular, en lugar de heredarlo de una clase en particular. Por lo tanto, AWS CDK proporciona su propia característica de interfaz como parte de la capa JSII.

Para indicar que una clase implementa una interfaz en particular, puede usar el decorador @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)

Dificultades de escritura

Python usa la escritura dinámica, en la que todas las variables pueden hacer referencia a un valor de cualquier tipo. Los parámetros y los valores devueltos se pueden anotar mediante escritura, pero se trata de “sugerencias” y no se aplican. Esto significa que en Python, es fácil pasar el tipo de valor incorrecto a un constructo de AWS CDK. En lugar de recibir un error de tipo durante la compilación, como ocurriría en un lenguaje de tipado estático, es posible que se produzca un error de tiempo de ejecución cuando la capa JSII (que traduce entre Python y el núcleo de AWS CDK TypeScript) no pueda procesar el tipo inesperado.

Según nuestra experiencia, los errores de tipo que cometen los programadores de Python suelen clasificarse en estas categorías.

  • Pasar un único valor donde un constructo espera un contenedor (lista o diccionario de Python) o viceversa.

  • Pasar un valor de un tipo asociado a una construcción de capa 1 (CfnXxxxxx) a un constructo de L2 o L3, o viceversa.

Los módulos de AWS CDK de Python incluyen anotaciones de tipos, por lo que puede usar herramientas que los admitan para ayudar con los tipos. Si no utiliza un IDE que los admita, como PyCharm, puede que desee llamar al validador de tipos MyPy como paso de su proceso de compilación. También hay comprobadores de tipos en tiempo de ejecución que pueden mejorar los mensajes de error relacionados con los tipos.