Lorsque je crée une couche AWS Lambda, tous les contenus / modules de mon fichier zip vont dans / opt /
lorsque AWS Lambda s'exécute. Cela devient facilement encombrant et frustrant car je dois utiliser des importations absolues sur tous mes lambdas. Exemple:
import json import os import importlib.util spec = importlib.util.spec_from_file_location("dynamodb_layer.customer", "/opt/dynamodb_layer/customer.py") module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) def fetch(event, context): CustomerManager = module.CustomerManager customer_manager = CustomerManager() body = customer_manager.list_customers(event["queryStringParameters"]["acquirer"]) response = { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*" }, "body": json.dumps(body) } return response
Alors je me demandais, est-il possible d'ajouter ces chemins / opt / à la variable d'environnement PATH au préalable via serverless.yml? De cette façon, je pourrais simplement depuis dynamodb_layer.customer importer CustomerManager
, au lieu de cette laideur bizarre.
4 Réponses :
Avez-vous essayé de paramétrer votre PYTHONPATH env var? https://stackoverflow.com/a/5944201/6529424
Avez-vous essayé d'ajouter à sys.path? https://stackoverflow.com/a/12257807/6529424
Ce ne sont pas des méthodes idiomatiques pour ajouter des modules et des packages importables à l'aide de couches Lambda. Voir ci-dessous.
J'ai une couche Lambda pour l'exécution Python3.6. Ma structure my_package.zip est:
layers: my_package: path: build compatibleRuntimes: - python3.6
Toutes les dépendances sont dans le dossier build
à la racine du projet:
par exemple. build/python/lib/python3.6/site-packages/customer
Section pertinente de mon serverless.yml
my_package.zip - python - lib - python3.6 - site-packages - customer
Dans mon Lambda, j'importe mon package comme je le ferais pour n'importe quel autre package:
importer un client
Savez-vous s'il existe un moyen de définir le chemin d'accès sans serveur? J'ai un tas de fichiers que je ne veux pas avoir à compresser dans une structure de répertoire spécifique, mais j'aimerais qu'ils se retrouvent dans /opt/python/lib/python3.6/site-packages / shared
. Y a-t-il un moyen de faire cela sans les organiser dans la même structure de répertoires dans git?
@Craig Votre script de construction peut manipuler les répertoires comme bon lui semble, avant de les empaqueter dans un fichier zip. Ceci est généralement appelé «mise en scène». Dans ce cas, votre build créerait un répertoire appelé 'python' puis y copierait les fichiers requis et les packages, avant de créer le zip et de le télécharger en tant que couche. Voir ma réponse par exemple!
Dans l'archive zip, le module doit être placé dans un sous-répertoire python
de sorte que lorsqu'il est extrait en tant que couche dans Lambda, il se trouve dans / opt / python < / code>. De cette façon, vous serez en mesure d'importer directement votre module sans avoir besoin de
importlib
.
C'est documenté ici a> ou consultez cet article de blog détaillé a> d'un évangéliste du développement AWS pour en savoir plus.
Les liens que vous fournissez ne semblaient pas assez explicites pour mon besoin d'utiliser mon (mes) propre (s) package (s) - c'est pourquoi j'ai écrit les choses un peu plus directement dans ma propre réponse ci-dessous,
Tant mieux pour toi mon pote. Vous n'êtes pas obligé de spammer les réponses de tout le monde ...
Désolé, vous vous sentez ennuyé, @milan - j'étais moi-même au milieu du problème et j'ai pensé que j'ajouterais des informations supplémentaires à l'usage des autres. Ce n'était en aucun cas du "spam" ou de l'auto-promotion. Et j'essaie de donner du crédit là où c'est dû. Si vous aviez de nouveaux détails pour un problème SO, j'espère que vous feriez de même.
Le paramétrage de la variable PYTHONPATH n'est pas obligatoire, tant que vous placez correctement les éléments dans le fichier zip.
Modules simples et répertoires de packages, ceux-ci doivent être placés dans un répertoire "python", puis tout le python / placé dans le fichier zip pour le téléchargement vers AWS en tant que couche. N'oubliez pas d'ajouter les paramètres "runtimes compatibles" (par exemple Python 3.6, 3.7, 3.8 ...) pour les couches.
Donc à titre d'exemple:
import json import os def lambda_handler(event, context): # TODO implement dir_list = os.listdir('/opt/python/') return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!'), 'event': json.dumps(event), '/opt/python/': dir_list }