AWS Lambda的conda环境

问题描述 投票:24回答:3

我想建立一个我在AWS Lambda上编写的Python函数,这个函数依赖于我已经在conda environment中收集的一堆Python库。

要在Lambda上进行设置,我应该将此环境压缩,但Lambda docs仅提供有关如何使用pip / VirtualEnv执行此操作的说明。有任何人对此有经验吗?

python amazon-web-services aws-lambda conda
3个回答
8
投票

你应该将serverless frameworkserverless-python-requirements plugin结合使用。您只需要一个requirements.txt,插件会自动将您的代码和依赖项打包到一个zip文件中,将所有内容上传到s3并部署您的函数。额外:因为它可以做到这个dockerized,它也能够帮助你处理需要二进制依赖的包。

看看here (https://serverless.com/blog/serverless-python-packaging/)的操作方法。

根据经验,我强烈建议你研究一下。用于部署的每一点手工劳动都可以阻止您开发逻辑。

编辑2017-12-17:

你的评论是有道理的@eelco-hoogendoorn

但是,在我看来,conda环境只是一个封装的地方,其中包含一堆python包。那么,如果您将所有这些依赖项(从您的conda env)放入requirements.txt(并使用无服务器+插件)来解决您的问题,不是吗? 恕我直言,它基本上与将您在env中安装的所有软件包压缩到部署包中相同。话虽这么说,这是一个片段,基本上这样做:

conda env export --name Name_of_your_Conda_env | yq -r '.dependencies[] | .. | select(type == "string")' | sed -E "s/(^[^=]*)(=+)([0-9.]+)(=.*|$)/\1==\3/" > requirements.txt

不幸的是,conda env export只以yaml格式导出环境。 --json标志现在不起作用,但应该在下一个版本中修复。这就是为什么我不得不使用yq而不是jq。你可以使用yq安装pip install yq。它只是jq的一个包装器,允许它也可以使用yaml文件。

记住

Lambda部署代码的大小只能为50MB。你的环境不应该太大。

我没有尝试使用serverless + serverless-python-packaging和像这样创建的requirements.txt部署lambda,我不知道它是否会起作用。


2
投票

I can't think of a good reason why zipping up your conda environment wouldn't work.

我想你可以进入你的anaconda2/envs/anaconda3/envs/目录并复制/压缩你要上传的env目录。 Conda只是virtualenv的一个加强版本,加上一个不同的,有些可选的包管理器。我认为没问题的一个重要原因是conda环境默认情况下将所有依赖项封装在其特定的.../anaconda[2|3]/envs/$VIRTUAL_ENV_DIR/目录中。

使用正常的virtualenv表达式可以让你获得更多的自由,就像洞穴人比现代人拥有更多自由一样。我个人比较喜欢汽车。使用virtualenv你基本上得到一个半空的$PYTHON_PATH变量,你可以填写你想要的任何东西,而不是Conda吐出的更强大,预先填充的env。以下是一个很好的参考表:https://conda.io/docs/commands.html#conda-vs-pip-vs-virtualenv-commands

Conda turns the command ~$ /path/to/$VIRTUAL_ENV_ROOT_DIR/bin/activate into ~$ source activate $VIRTUAL_ENV_NAME

假设你想用老式的方式制作virtualenv。你要选择一个目录(让我们称之为$VIRTUAL_ENV_ROOT_DIR,)和名称(我们称之为$VIRTUAL_ENV_NAME。)此时你会输入:

~$ cd $VIRTUAL_ENV_ROOT_DIR && virtualenv $VIRTUAL_ENV_NAME

然后python创建它自己的解释器库的副本(我认为还有pip和setuptools)并在这个克隆的activate目录中放置一个名为bin/的可执行文件。 $VIRTUAL_ENV_ROOT_DIR/bin/activate脚本的工作原理是改变你当前的$PYTHONPATH环境变量,它确定当你在shell中键入~$ python时调用python解释器,以及包含解释器在被告知import时会看到的所有模块的目录列表。这是你在人们的代码而不是#!/usr/bin/env python中看到/usr/bin/python的主要原因。


2
投票

我使用conda的主要原因是不要自己编译不同的二进制包(如numpymatplotlibpyqt等)或者不经常编译它们。如果你确实需要为python的特定版本(如uwsgi)自己编译一些东西,你应该使用与gcc环境中编译的python相同的conda版本编译二进制文件 - 很可能它与你的gcc不一样操作系统正在使用,因为conda现在使用的gcc应该与conda install gxx_linux-64一起安装的最新版本。

这导致我们出现两种情况:

  1. 你所有的依赖都在纯python中,你实际上可以使用pip freeze保存它们的列表列表,并按照virtualenv的说明捆绑它们。
  2. 你有一些二进制扩展。在这种情况下,来自conda环境的二进制文件将无法与AWS lambda使用的python一起使用。不幸的是,您需要访问描述执行环境的page(AMI:amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2),设置环境,为特定版本的内置python构建二进制文件单独的目录(以及纯python包),然后将它们捆绑到zip-archive中。

这是对您的问题的一般答案,但主要思想是您不能重复使用二进制包,只能重用它们的列表。