在 AWS Lambda 的子目录中打包 Python 个依赖项

Packaging Python dependencies in subdirectory for AWS Lambda

我遇到了一个关于为 AWS Lambda 构建 Python 3 个应用程序的 article on serverlesscode.com,它建议使用 pip(或 pip3)在 /vendored 子目录中安装依赖项。我喜欢这个想法,因为它使文件结构保持整洁,但我在实现它时遇到了一些问题。

我正在使用无服务器框架,我的模块以正常方式导入到我的代码中,例如from pynamodb.models import Model

我已经使用命令 pip install -t vendored/ -r requirements.txt 在子目录中安装我的各种依赖项(根据 requirements.txt),这似乎按预期工作 - 我可以看到安装在子目录中的所有模块。

然而,当调用该函数时,我收到错误 Unable to import module 'handler': No module named 'pynamodb'(其中 pynamodb 是已安装的模块之一)。

我可以通过将我的 pip 安装更改为项目根目录来解决此错误,即不在 /vendored 文件夹中 (pip install -t ./ -r requirements.txt)。这将安装完全相同的文件。

一定有一个指向子文件夹的配置我遗漏了,但谷歌搜索没有显示我是否需要以不同的方式导入我的模块,或者是否有一些其他的全局配置我需要改变。

总结一下:如何使用 Pip 将我的依赖项安装到项目的子文件夹中?

编辑:注意到tkwargs关于使用无服务器插件打包的好建议,了解如何使用仍然很好例如,这可以在没有 venv 的情况下完成。主要目的不是专门为了使打包更容易(使用 pip 非常简单),而是通过避免在根目录中添加其他文件夹来保持我的文件结构更清晰。

我看到有些人在他们的 lambda 函数的代码中使用 sys 模块来添加子目录,在这种情况下,vendored,到他们的 python 路径......我不喜欢那个,因为一个解决方案,因为这意味着需要为每个 lambda 函数执行此操作,并需要额外的样板代码。我最终使用的解决方案是修改 PYTHONPATH 运行时环境变量以包含我的子目录。例如,在我的 serverless.yml 中,我有:

provider:
  environment:
    PYTHONPATH: '/var/task/vendored:/var/runtime'

通过在此级别将其设置为环境变量,它将应用于您在 serverless.yml 中部署的每个 lambda 函数——如果出于某种原因您也可以在每个 lambda 函数级别指定它不希望它应用于所有这些。

我不确定如何自我引用 PYTHONPATH 的现有值以确保我在添加自定义路径“/var/task/vendored”的过程中没有错误地覆盖它...很想知道有没有人有。