Blog
Python und relative Importe in AWS Lambda-Funktionen

Wenn Sie eine AWS Lambda-Funktion schreiben, ist es gut möglich, dass Sie an einen Punkt kommen, an dem die Datei zu groß wird. Was tun Sie dann? Sie erstellen eine zweite Datei und refaktorisieren Ihren Code, um einen relativen Import durchzuführen. Dann bleibt nur noch der Schritt, Ihren Code zu verteilen und auszuführen. Und dann schlägt es fehl... Waren Sie schon einmal hier? Dann habe ich vielleicht einen guten Rat für Sie.
Wenn Sie sich den PEP 8 -- Style Guide for Python Code ansehen. , werden Sie lesen, dass werden absolute Importe empfohlen. Aber explizite relative Importe sind eine akzeptable Alternative zu absoluten Importen . Das bedeutet, dass Sie absolute Importe bevorzugen sollten. Und nur relative Importe innerhalb eines Pakets verwenden.
Beispiel-Code
Lassen Sie uns eine Hallo-Welt-Lambdafunktion erstellen, um dies zu zeigen. Wir haben also den folgenden Code in einer Datei namens hello_world/app.py:
import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps({"message": "hello world"}),
}
Der Einfachheit halber habe ich das AWS Serverless Application Model verwendet. Die Vorlagen enthalten die folgende Ressource:
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.9
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
Das Wichtigste ist die Definition von Handler. Der Wert app.lambda_handler bedeutet soviel wie:
Verwenden Sie die Dateiapp.pyund rufen Sie die Methodelambda_handlerauf.
Wir werden nun die Nutzlast in eine Datei namens hello_world/response.py verschieben:
def get_response() -> dict:
return {"message": "hello world"}
Und aktualisieren Sie die hello_world/app.py:
import json
from .response import get_response
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps(get_response()),
}
Sie führen Ihren Test aus und er funktioniert, gut! Also stellen wir jetzt unseren Code bereit und hoffen, dass er auch funktioniert. Und er schlägt fehl...
[ERROR] Runtime.ImportModuleError: Unable to import module 'app': attempted relative import with no known parent package
Traceback (most recent call last):
Der Inhalt des Ordners hello_world landet in dem Ordner /var/task/. Und nicht der Ordner selbst.
Es könnte also so aussehen, als befände sich der Code in einem Paket, aber von der Lambda-Laufzeit aus gesehen ist er es nicht.
Die Lösung
Sie können dieses Problem lösen, indem Sie ein Paket erstellen. Wie, werden Sie fragen? Erstellen Sie einen Ordner hello_world im Ordner hello_world.
Verschieben Sie alle Dateien außer requirements.txt in den erstellten Ordner.
Als nächstes müssen Sie die Handler in der Vorlage aktualisieren:
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: hello_world.app.lambda_handler
Runtime: python3.9
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
Der Wert von Handler entspricht nun dem:
Im Pakethello_worldverwenden Sie die Dateiapp.pyund rufen die Methodelambda_handlerauf.
Bei der Bereitstellung werden Sie nun feststellen, dass der relative Import funktioniert.
Fazit
Ich würde Ihnen immer empfehlen, Ihren Python-Code in einem Paket bereitzustellen. Es macht es einfacher, viele Dateien zu verwenden und Ihren Code besser zu organisieren. Außerdem können Sie so die Logik der Lambda-Aufrufe von Ihrer Geschäftslogik trennen. Das macht es einfacher zu testen und zu warten.
Bild von Gerd Altmann von Pixabay
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


