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

H O*_*H O 5 python pip aws-lambda serverless-framework python-packaging

我在serverlesscode.com 遇到了有关为AWS Lambda构建Python 3应用程序的文章,文章建议使用pip(或pip3)在/ vendored子目录中安装依赖项。我喜欢这个主意,因为它可以使文件结构保持整洁,但是在实现它方面存在一些问题。

我正在使用Serverless Framework,并且我的模块以正常方式导入到我的代码中,例如 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)中)来解决此错误。这将安装完全相同的文件。

我必须缺少一个指向子文件夹的配置,但是Googling并未透露我是否需要以其他方式导入模块,或者是否需要更改其他全局配置。

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

编辑:注意到tkwargs关于使用无服务器插件进行打包的好建议,例如,如果没有venv,那么了解如何做到这一点仍然会很好。主要目的不是专门为了简化打包(使用pip相当容易),而是通过避免在根目录中放置其他文件夹来保持文件结构更整洁。

小智 8

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

provider:
  environment:
    PYTHONPATH: '/var/task/vendored:/var/runtime'
Run Code Online (Sandbox Code Playgroud)

通过在此级别将其设置为环境变量,它将应用于您在 serverless.yml 中部署的每个 lambda 函数——如果由于某种原因您不想将其应用于每个 lambda 函数级别,您也可以在每个 lambda 函数级别指定它他们都。

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