【问题标题】:AWS Lambda in Python: Import parent package/directory in Lambda function handlerPython 中的 AWS Lambda:在 Lambda 函数处理程序中导入父包/目录
【发布时间】:2020-05-02 23:08:20
【问题描述】:

我在使用 AWS SAM 和 Python 3.8 作为运行时创建的无服务器应用程序(避免混乱的最简单应用程序)中有如下目录结构:

├── common
│   └── a.py
├── hello_world
│   ├── __init__.py
│   ├── app.py
│   └── requirements.txt
└── template.yaml

我想在 Lambda 处理程序中导入 common/a.py 模块 - hello_world/app.py。现在我知道我可以通过添加PYTHONPATHsys.path 的路径来import it normally in Python,但是当代码在Docker 容器内的Lambda 中运行时它不起作用。调用时,Lambda 处理函数在/var/task 目录中运行,不考虑文件夹结构。

我尝试像这样以编程方式将/var/task/common/var/common/var 甚至/common 插入到sys.path

import sys
sys.path.insert(0, '/var/task/common')
from common.a import Alpha

但我仍然收到错误:

ModuleNotFoundError: No module named 'common'

我知道Lambda Layers,但考虑到我的场景,我想直接引用多个 Lambda 函数中的公共代码,而不需要上传到层。我想在 无服务器框架 但在 AWS SAM 中拥有类似 serverless-python-requirements 的插件。

所以我的问题是,我应该如何将此路径添加到commonPYTHONPATHsys.path?或者有没有像[serverless-python-requirements][3] 这样的替代解决方法,直接在父文件夹中导入模块而不使用 Lambda 层?

【问题讨论】:

  • 你必须创建包“common”并导入它。 geeksforgeeks.org/create-access-python-package
  • lambda 适用于虚拟环境。 /var/task/ 创建我们将无法获取导入路径的运行时。最好你有创建包名称“通用”文件夹名称。
  • 我无法理解这一点:“最好你有创建包名称“通用”文件夹名称。”您的意思是单独部署包吗,因为就像我提到的那样,公共文件夹已经是 Python 3.3+ 中的包,而且我知道 Lambda 是一个虚拟环境,这就是我想要解决方法的原因。能否请您详细说明一下?
  • 我是说你不能使用通用名称作为文件夹或导入。因为它不能将您的自定义文件夹覆盖到虚拟环境文件夹。您可以使用“共享”或系统关键字未附带的其他内容。
  • sys.path 或没有sys.path,这对我来说无关紧要。我只想要一种从 Lambda 函数处理程序中的父文件夹导入模块的方法。如果您知道答案,请考虑发布一个并提及详细信息!

标签: python python-3.x aws-lambda aws-sam aws-sam-cli


【解决方案1】:

我在包依赖项方面遇到了类似问题,根据 AWS 知识中心,您应该将所有项目放在根级别:

您可能需要创建一个部署包,其中包含 位于 .zip 文件根目录中的功能模块具有读取和 所有文件的执行权限。

根据https://aws.amazon.com/premiumsupport/knowledge-center/build-python-lambda-deployment-package/

【讨论】:

    【解决方案2】:

    我没有找到我要找的东西,但我最终找到了一个解决方案,即在根目录中创建一个 Lambda 函数,该函数处理函数中所有不同的 API 调用。是的,我的 Lambda 函数与 API Gateway 集成,我可以分别使用 event["httpMethod"]event ["httpPath"] 获取 API 方法和 API 路径。然后我可以将所有包放在根目录下并相互导入。

    例如,假设我有 2 个 API 路径 /items/employees 需要处理,并且它们都需要处理 GET 和 POST 方法,以下代码就足够了:

    if event["path"] == '/items':
       if event["httpMethod"] == 'GET':
          ...
       elif event["httpMethod"] == 'POST':
          ...
    elif event["path"] == '/employees':
       if event["httpMethod"] == 'GET':
          ...
       if event["httpMethod"] == 'POST':
          ...
    

    所以现在我可以在这个 Lambda 函数下拥有尽可能多的包。例如,下面是仓库现在的样子:

    ├── application
    │   └── *.py
    ├── persistence
    │   └── *.py
    ├── models
    │   └── *.py
    └── rootLambdaFunction.py
    └── requirements.txt
    

    这样,我可以在给定结构中随意导入包。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-08
      • 1970-01-01
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      • 2019-01-27
      相关资源
      最近更新 更多