Blog
Relative Python-Importe in einer Dockerized-Lambda-Funktion

Relative Python-Importe können für Lambda-Funktionen schwierig sein. Ich habe vor 3 Jahren einen Blog darüber geschrieben. Aber vor kurzem bin ich auf das gleiche Problem mit Dockerized Lambda-Funktionen gestoßen. Also dachte ich mir, es ist Zeit für einen neuen Blog!
Sie können den Schritten folgen oder sich das Ergebnis direkt auf GitHub ansehen.
Projekt einrichten
Stellen Sie sicher, dass Sie das AWS CDK cli installiert haben.
brew install aws-cdk
Initialisieren Sie das Projekt:
cdk init app --language=typescript
Lambda-Einrichtung
Zunächst müssen wir die Datei- und Ordnerstruktur erstellen:
mkdir -p lib/functions/hello-world/hello_world
touch lib/functions/hello-world/hello_world/__init__.py
touch lib/functions/hello-world/hello_world/business_logic.py
touch lib/functions/hello-world/requirements.txt
touch lib/functions/hello-world/Dockerfile
Nun müssen Sie das Dockerfile wie folgt füllen:
FROM public.ecr.aws/lambda/python:3.12
COPY requirements.txt .
COPY hello_world ${LAMBDA_TASK_ROOT}/hello_world
RUN pip install --no-cache-dir -r requirements.txt
CMD ["hello_world.handler"]
Wir verwenden ein Python-Basis-Image, das auf Python 3.12 basiert. Als nächstes kopieren wir die Datei requirements.txt aufgeführten Abhängigkeiten und stellen sicher, dass die Methode handler als CMD eingestellt ist.
Als nächstes müssen wir unsere Python-Dateien mit etwas Code füllen. In der Datei __init__.py können Sie den folgenden Inhalt platzieren:
from typing import Dict, Any
# Example of the relative import
from .business_logic import business_logic
def handler(event: Dict[str, Any], context: Any) -> Dict[str, str]:
# User the method that is imported based on a relative path
name = business_logic(event)
return {
"Name": name,
"Message": f"Hello {name}!",
}
__all__ = [
"handler"
]
Danach müssen wir die Datei business_logic.py füllen:
from typing import Dict, Any
def business_logic(event: Dict[str, Any]) -> str:
return event.get("name", "World")
HINWEIS: Der hier verwendete Code könnte mehrere relative Importe verwenden. Dies ist möglich, weil er sich in einem separaten Paket befindet. Dieses Beispiel zeigt nur ein Beispiel in der Datei
. Sie können hier jedoch mehrere Dateien verwenden, um die Wartbarkeit Ihres Projekts zu verbessern.
Für dieses Beispiel benötige ich keine Abhängigkeiten, also können wir die Datei requirements.txt leer lassen. Ich habe sie in dieses Beispiel aufgenommen, um zu zeigen, wie Sie auch Abhängigkeiten einfügen können.
Erstellen Sie die Lambda-Funktion mit IaC
Unsere Ordner und Dateien sind vorhanden. Es ist nun an der Zeit, die Lambda-Funktion zum CDK-Konstrukt hinzuzufügen. Sie können sie einfach wie folgt hinzufügen:
new lambda.Function(this, 'Function', {
functionName: "hello-world",
code: lambda.Code.fromAssetImage("lib/functions/hello-world", {
platform: ecr_assets.Platform.LINUX_ARM64,
}),
runtime: lambda.Runtime.FROM_IMAGE,
handler: lambda.Handler.FROM_IMAGE,
architecture: lambda.Architecture.ARM_64,
timeout: cdk.Duration.seconds(15),
memorySize: 128,
});
Damit dies funktioniert, benötigen Sie außerdem die folgenden Importe:
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';
Beachten Sie, dass wir darauf achten, dass das Code-Verzeichnis auf das Verzeichnis verweist, das die Dockerfile enthält, und dass wir die ARM-Plattform sowohl für den Code als auch für die Funktion selbst auswählen.
Die Lambda-Funktion lokal testen
Schnelles Feedback ist wichtig, daher kann es vorkommen, dass Sie den Container lokal ausführen müssen. Dazu müssen Sie zunächst den Container erstellen:
docker build --platform linux/arm64
-t hello-world:latest
-f ./lib/functions/hello-world/Dockerfile
./lib/functions/hello-world
Beachten Sie, dass dieser Befehl vom Stammverzeichnis des Projekts aus ausgeführt werden kann. Als nächstes müssen wir sicherstellen, dass er ausgeführt wird, bevor wir ihn aufrufen können:
docker run --platform linux/arm64 -p 9000:8080 hello-world:latest
Danach können Sie die Funktion wie folgt aufrufen:
curl http://localhost:9000/2015-03-31/functions/function/invocations -d '{"name": "Joris"}'
Fazit
Relative Importe können knifflig sein! Sie müssen Ihren Code in einem Paket unterbringen. So können Sie relative Importe innerhalb Ihres eigenen Pakets durchführen. Dies ermöglicht einen saubereren Code, da Sie die Verantwortlichkeiten in mehrere Dateien aufteilen können, was die Verwaltung und Pflege erleichtert.
Foto von Kaique Rocha
Verfasst von

Joris Conijn
Joris is the AWS Practise CTO of the Xebia Cloud service line and has been working with the AWS cloud since 2009 and focussing on building event-driven architectures. While working with the cloud from (almost) the start, he has seen most of the services being launched. Joris strongly believes in automation and infrastructure as code and is open to learning new things and experimenting with them because that is the way to learn and grow.
Unsere Ideen
Weitere Blogs
Contact



