在亚马逊 lambda 中使用 moviepy、scipy 和 numpy
Using moviepy, scipy and numpy in amazon lambda
我想使用 AWS Lambda
功能生成视频。
我现在有以下过程来构建我的 Lambda
函数:
第 1 步
触发一个 Amazon Linux EC2
实例并 运行 以 root 身份运行它:
#! /usr/bin/env bash
# Install the SciPy stack on Amazon Linux and prepare it for AWS Lambda
yum -y update
yum -y groupinstall "Development Tools"
yum -y install blas --enablerepo=epel
yum -y install lapack --enablerepo=epel
yum -y install atlas-sse3-devel --enablerepo=epel
yum -y install Cython --enablerepo=epel
yum -y install python27
yum -y install python27-numpy.x86_64
yum -y install python27-numpy-f2py.x86_64
yum -y install python27-scipy.x86_64
/usr/local/bin/pip install --upgrade pip
mkdir -p /home/ec2-user/stack
/usr/local/bin/pip install moviepy -t /home/ec2-user/stack
cp -R /usr/lib64/python2.7/dist-packages/numpy /home/ec2-user/stack/numpy
cp -R /usr/lib64/python2.7/dist-packages/scipy /home/ec2-user/stack/scipy
tar -czvf stack.tgz /home/ec2-user/stack/*
第 2 步
我将生成的 tarball scp 到我的笔记本电脑。然后 运行 这个脚本来构建一个 zip 存档。
#! /usr/bin/env bash
mkdir tmp
rm lambda.zip
tar -xzf stack.tgz -C tmp
zip -9 lambda.zip process_movie.py
zip -r9 lambda.zip *.ttf
cd tmp/home/ec2-user/stack/
zip -r9 ../../../../lambda.zip *
process_movie.py
脚本目前只是测试堆栈是否正常:
def make_movie(event, context):
import os
print(os.listdir('.'))
print(os.listdir('numpy'))
try:
import scipy
except ImportError:
print('can not import scipy')
try:
import numpy
except ImportError:
print('can not import numpy')
try:
import moviepy
except ImportError:
print('can not import moviepy')
第 3 步
然后我将生成的存档上传到 S3 作为我的 lambda
函数的来源。
当我测试该功能时,我得到以下 callstack
:
START RequestId: 36c62b93-b94f-11e5-9da7-83f24fc4b7ca Version: $LATEST
['tqdm', 'imageio-1.4.egg-info', 'decorator.pyc', 'process_movie.py', 'decorator-4.0.6.dist-info', 'imageio', 'moviepy', 'tqdm-3.4.0.dist-info', 'scipy', 'numpy', 'OpenSans-Regular.ttf', 'decorator.py', 'moviepy-0.2.2.11.egg-info']
['add_newdocs.pyo', 'numarray', '__init__.py', '__config__.pyc', '_import_tools.py', 'setup.pyo', '_import_tools.pyc', 'doc', 'setupscons.py', '__init__.pyc', 'setup.py', 'version.py', 'add_newdocs.py', 'random', 'dual.pyo', 'version.pyo', 'ctypeslib.pyc', 'version.pyc', 'testing', 'dual.pyc', 'polynomial', '__config__.pyo', 'f2py', 'core', 'linalg', 'distutils', 'matlib.pyo', 'tests', 'matlib.pyc', 'setupscons.pyc', 'setup.pyc', 'ctypeslib.py', 'numpy', '__config__.py', 'matrixlib', 'dual.py', 'lib', 'ma', '_import_tools.pyo', 'ctypeslib.pyo', 'add_newdocs.pyc', 'fft', 'matlib.py', 'setupscons.pyo', '__init__.pyo', 'oldnumeric', 'compat']
can not import scipy
'module' object has no attribute 'core': AttributeError
Traceback (most recent call last):
File "/var/task/process_movie.py", line 91, in make_movie
import numpy
File "/var/task/numpy/__init__.py", line 122, in <module>
from numpy.__config__ import show as show_config
File "/var/task/numpy/numpy/__init__.py", line 137, in <module>
import add_newdocs
File "/var/task/numpy/numpy/add_newdocs.py", line 9, in <module>
from numpy.lib import add_newdoc
File "/var/task/numpy/lib/__init__.py", line 13, in <module>
from polynomial import *
File "/var/task/numpy/lib/polynomial.py", line 11, in <module>
import numpy.core.numeric as NX
AttributeError: 'module' object has no attribute 'core'
END RequestId: 36c62b93-b94f-11e5-9da7-83f24fc4b7ca
REPORT RequestId: 36c62b93-b94f-11e5-9da7-83f24fc4b7ca Duration: 112.49 ms Billed Duration: 200 ms Memory Size: 1536 MB Max Memory Used: 14 MB
我不明白为什么 python 找不到文件夹结构中存在的核心目录。
编辑:
按照@jarmod 的建议,我将 lambda
函数缩减为:
def make_movie(event, context):
print('running make movie')
import numpy
我现在有以下错误:
START RequestId: 6abd7ef6-b9de-11e5-8aee-918ac0a06113 Version: $LATEST
running make movie
Error importing numpy: you should not try to import numpy from
its source directory; please exit the numpy source tree, and relaunch
your python intepreter from there.: ImportError
Traceback (most recent call last):
File "/var/task/process_movie.py", line 3, in make_movie
import numpy
File "/var/task/numpy/__init__.py", line 127, in <module>
raise ImportError(msg)
ImportError: Error importing numpy: you should not try to import numpy from
its source directory; please exit the numpy source tree, and relaunch
your python intepreter from there.
END RequestId: 6abd7ef6-b9de-11e5-8aee-918ac0a06113
REPORT RequestId: 6abd7ef6-b9de-11e5-8aee-918ac0a06113 Duration: 105.95 ms Billed Duration: 200 ms Memory Size: 1536 MB Max Memory Used: 14 MB
我也在关注你的第一个 link 并设法在 Lambda 中导入 numpy 和 pandas以这种方式运行(在 Windows 上):
- 使用 64 位 Amazon Linux AMI 2015.09.1 启动了 (free-tier) t2.micro EC2 instance 并使用Putty 到 SSH 中。
尝试了与您使用的相同命令以及亚马逊文章推荐的命令:
sudo yum -y update
sudo yum -y upgrade
sudo yum -y groupinstall "Development Tools"
sudo yum -y install blas --enablerepo=epel
sudo yum -y install lapack --enablerepo=epel
sudo yum -y install Cython --enablerepo=epel
sudo yum install python27-devel python27-pip gcc
创建了虚拟环境:
virtualenv ~/env
source ~/env/bin/activate
安装了 软件包:
sudo ~/env/bin/pip2.7 install numpy
sudo ~/env/bin/pip2.7 install pandas
然后,我使用 WinSCP 登录并下载所有内容(_markerlib、pip*、pkg_resources、setuptools* 和 easyinstall* 除外)来自 /home/ec2-user/env/lib/python2.7/dist-packages
,以及来自 /home/ec2-user/env/lib64/python2.7/site-packages
的所有内容来自 EC2 实例。
我将所有这些文件夹和文件与包含 Lambda 函数的 .py 文件一起放入一个 zip 中。
illustration of all files copied
因为这个 .zip 大于 10 MB,所以我创建了一个 S3 存储桶 来存储文件。我从那里复制了文件的 link 并粘贴到 Lambda 函数的 "Upload a .ZIP from Amazon S3"。
EC2实例可以关闭,不再需要了。
有了这个,我可以导入 numpy 和 pandas。我不熟悉 moviepy,但 scipy 可能已经很棘手了,因为 Lambda 有一个 limit 解压缩部署包大小为 262 144 000 字节。恐怕 numpy 和 scipy 一起已经结束了。
在此线程中的所有帖子的帮助下,这里是记录的解决方案:
要使其正常工作,您需要:
用至少 2GO RAM 启动一个 EC2
实例(以便能够编译 NumPy
& SciPy
)
安装所需的依赖项
sudo yum -y update
sudo yum -y upgrade
sudo yum -y groupinstall "Development Tools"
sudo yum -y install blas --enablerepo=epel
sudo yum -y install lapack --enablerepo=epel
sudo yum -y install Cython --enablerepo=epel
sudo yum install python27-devel python27-pip gcc
virtualenv ~/env
source ~/env/bin/activate
pip install scipy
pip install numpy
pip install moviepy
将 stack
文件夹中目录(_markerlib、pip*、pkg_resources、setuptools* 和 easyinstall* 除外)的所有内容复制到您的语言环境机器:
home/ec2-user/env/lib/python2.7/dist-packages
home/ec2-user/env/lib64/python2.7/dist-packages
从您那里获取所有需要的共享库EC2
实例:
libatlas.so.3
libf77blas.so.3
liblapack.so.3
libptf77blas.so.3
libcblas.so.3
libgfortran.so.3
libptcblas.so.3
libquadmath.so.0
将它们放在 stack
文件夹的 lib
子文件夹中
imageio
是 moviepy
的依赖项,您需要下载其依赖项的一些二进制版本:libfreeimage
和 ffmpeg
;可以找到它们 here。将它们放在堆栈文件夹的根目录下,并将 libfreeimage-3.16.0-linux64.so
重命名为 libfreeimage.so
您现在应该有一个 stack
文件夹,其中包含:
- 所有 python 根依赖关系
lib
子文件夹中的所有共享库
ffmpeg
根目录下的二进制文件
libfreeimage.so
在根目录
压缩此文件夹:zip -r9 stack.zip . -x ".*" -x "*/.*"
使用以下 lambda_function.py
作为您的 lambda
的入口点
from __future__ import print_function
import os
import subprocess
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
LIB_DIR = os.path.join(SCRIPT_DIR, 'lib')
FFMPEG_BINARY = os.path.join(SCRIPT_DIR, 'ffmpeg')
def lambda_handler(event, context):
command = 'LD_LIBRARY_PATH={} IMAGEIO_FFMPEG_EXE={} python movie_maker.py'.format(
LIB_DIR,
FFMPEG_BINARY,
)
try:
output = subprocess.check_output(command, shell=True)
print(output)
except subprocess.CalledProcessError as e:
print(e.output)
写一个 movie_maker.py
脚本依赖于 moviepy
, numpy
, ...
将这些脚本添加到您的 stack.zip 文件 zip -r9 lambda.zip *.py
将 zip 上传到 S3
并将其用作您的 lambda
的来源
您还可以下载 stack.zip
here.
这里的帖子帮助我找到了一种使用可包含在 AWS Lambda 部署包中的库文件静态编译 NumPy 的方法。此解决方案不像@rouk1 解决方案那样依赖于 LD_LIBRARY_PATH 值。
编译好的NumPy库可以从https://github.com/vitolimandibhrata/aws-lambda-numpy
下载
这里是自定义编译NumPy的步骤
从头开始编译这个包的说明
使用 AWS Linux.
准备一个新的 AWS EC 实例
安装编译器依赖项
sudo yum -y install python-devel
sudo yum -y install gcc-c++
sudo yum -y install gcc-gfortran
sudo yum -y install libgfortran
安装 NumPy 依赖项
sudo yum -y install blas
sudo yum -y install lapack
sudo yum -y install atlas-sse3-devel
创建 /var/task/lib 以包含运行时库
mkdir -p /var/task/lib
/var/task 是您的代码将驻留在 AWS Lambda 中的根目录,因此我们需要将所需的库文件静态 link 在一个众所周知的文件夹中,在本例中为 /var/task/lib
将以下库文件复制到/var/task/lib
cp /usr/lib64/atlas-sse3/liblapack.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libptf77blas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libf77blas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libptcblas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libcblas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libatlas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libptf77blas.so.3 /var/task/lib/.
cp /usr/lib64/libgfortran.so.3 /var/task/lib/.
cp /usr/lib64/libquadmath.so.0 /var/task/lib/.
从http://sourceforge.net/projects/numpy/files/NumPy/
获取最新的numpy源代码
转到 numpy 源代码文件夹,例如 numpy-1.10.4
使用以下条目创建一个 site.cfg 文件
[atlas]
libraries=lapack,f77blas,cblas,atlas
search_static_first=true
runtime_library_dirs = /var/task/lib
extra_link_args = -lgfortran -lquadmath
-lgfortran -lquadmath 标志需要静态 link gfortran 和 quadmath 库以及 runtime_library_dirs
中定义的文件
构建 NumPy
python setup.py build
安装 NumPy
python setup.py install
检查库是否linked到/var/task/lib
中的文件
ldd $PYTHON_HOME/lib64/python2.7/site-packages/numpy/linalg/lapack_lite.so
你应该看看
linux-vdso.so.1 => (0x00007ffe0dd2d000)
liblapack.so.3 => /var/task/lib/liblapack.so.3 (0x00007ffad6be5000)
libptf77blas.so.3 => /var/task/lib/libptf77blas.so.3 (0x00007ffad69c7000)
libptcblas.so.3 => /var/task/lib/libptcblas.so.3 (0x00007ffad67a7000)
libatlas.so.3 => /var/task/lib/libatlas.so.3 (0x00007ffad6174000)
libf77blas.so.3 => /var/task/lib/libf77blas.so.3 (0x00007ffad5f56000)
libcblas.so.3 => /var/task/lib/libcblas.so.3 (0x00007ffad5d36000)
libpython2.7.so.1.0 => /usr/lib64/libpython2.7.so.1.0 (0x00007ffad596d000)
libgfortran.so.3 => /var/task/lib/libgfortran.so.3 (0x00007ffad5654000)
libm.so.6 => /lib64/libm.so.6 (0x00007ffad5352000)
libquadmath.so.0 => /var/task/lib/libquadmath.so.0 (0x00007ffad5117000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ffad4f00000)
libc.so.6 => /lib64/libc.so.6 (0x00007ffad4b3e000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ffad4922000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007ffad471d000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007ffad451a000)
/lib64/ld-linux-x86-64.so.2 (0x000055cfc3ab8000)
我喜欢@Vito Limandibhrata 的回答,但我认为在 numpy==1.11.1 中使用 runtime_library_dirs 构建 numpy 是不够的。如果有人认为 site-cfg 被忽略,请执行以下操作:
cp /usr/lib64/atlas-sse3/*.a /var/task/lib/
*.a 需要atlas-sse3 下的文件来构建numpy。此外,您可能需要 运行 以下内容:
python setup.py config
检查 numpy 配置。如果需要更多信息,您将看到以下消息:
atlas_threads_info:
Setting PTATLAS=ATLAS libraries ptf77blas,ptcblas,atlas not found in /root/Envs/skl/lib
libraries lapack_atlas not found in /root/Envs/skl/lib
libraries ptf77blas,ptcblas,atlas not found in /usr/local/lib64
libraries lapack_atlas not found in /usr/local/lib64
libraries ptf77blas,ptcblas,atlas not found in /usr/local/lib
libraries lapack_atlas not found in /usr/local/lib
libraries lapack_atlas not found in /usr/lib64/atlas-sse3
<class 'numpy.distutils.system_info.atlas_threads_info'>
Setting PTATLAS=ATLAS
Setting PTATLAS=ATLAS
Setting PTATLAS=ATLAS
Setting PTATLAS=ATLAS
libraries lapack not found in ['/var/task/lib']
Runtime library lapack was not found. Ignoring
libraries f77blas not found in ['/var/task/lib']
Runtime library f77blas was not found. Ignoring
libraries cblas not found in ['/var/task/lib']
Runtime library cblas was not found. Ignoring
libraries atlas not found in ['/var/task/lib']
Runtime library atlas was not found. Ignoring
FOUND:
extra_link_args = ['-lgfortran -lquadmath']
define_macros = [('NO_ATLAS_INFO', -1)]
language = f77
libraries = ['lapack', 'ptf77blas', 'ptcblas', 'atlas', 'lapack', 'f77blas', 'cblas', 'atlas']
library_dirs = ['/usr/lib64/atlas-sse3']
include_dirs = ['/usr/include']
然后 site-cfg 将被忽略。
提示:如果使用pip构建numpy runtime_library_dirs,最好创建~/.numpy-site.cfg
并添加以下内容:
[atlas]
libraries = lapack,f77blas,cblas,atlas
search_static_first = true
runtime_library_dirs = /var/task/lib
extra_link_args = -lgfortran -lquadmath
然后 numpy 识别 .numpy-site.cfg 文件。这是非常简单易行的方法。
另一种非常简单的方法是使用 LambCI 为模仿 Lambda 而制作的很棒的 docker 容器进行构建:https://github.com/lambci/docker-lambda
lambci/lambda:build
容器类似于 AWS Lambda,但增加了 mostly-complete 构建环境。要在其中启动 shell 会话:
docker run -v "$PWD":/var/task -it lambci/lambda:build bash
会话内部:
export share=/var/task
easy_install pip
pip install -t $share numpy
或者,使用 virtualenv:
export share=/var/task
export PS1="[\u@\h:\w]$ " # required by virtualenv
easy_install pip
pip install virtualenv
# ... make the venv, install numpy, and copy it to $share
稍后您可以使用 lambci/lambda 主容器来测试您的构建。
截至 2017 年,NumPy 和 SciPy 具有可在 Lambda 上运行的轮子(这些包包括预编译的 libgfortran
和 libopenblas
)。
据我所知,MoviePy 是一个纯粹的 Python 模块,所以基本上你可以这样做:
pip2 install -t lambda moviepy scipy
然后将您的处理程序复制到 lambda
目录并压缩。除了,您很可能会超过 50/250 MB 的大小限制。有几件事可以提供帮助:
- 删除.pycs、文档、测试和其他不需要的部分;
- 保留 NumPy 和 SciPy 公共库的单个副本;
- 剥离不必要的库,例如调试符号;
- 使用更高的设置压缩存档。
这里有一个例子script,可以自动执行上述几点。
我可以确认@attila-tanyi 发布的步骤在 Amazon Linux 下可以正常工作。我只想补充一点,不需要使用 EC2,因为默认存储库中有一个 Amazon Linux docker 容器可用。
docker pull amazonlinux && docker run -it amazonlinux
# Follow @attila-tanyi steps
# Note - sudo is not necessary here
我使用应用程序中嵌入的 Dockerfile 来构建和部署到 Lambda。
截至 2018 年,在 AWS EC2 Python3 中安装外部模块的步骤:
在 Amazon Linux AMI 201709 上启动 EC2。
使用私钥和 public 密钥通过 putty ssh 并成为超级用户。
安装Python 3 并创建虚拟环境,然后将其设为默认值
yum install python36 python36-virtualenv python36-pip
virtualenv -p python3.6 /tmp/my_python_lib
source /tmp/my_python_lib/bin/activate
which python --to check which version s installed
pip3 install numpy
使用winscp将站点包和dist包下的文件复制到本地机器中。
要查找实际位置,请使用 grep 命令 ---
grep -r dist-packages *.
这些包可能在 lib 和 lib64 中。
站点和 dist 包将位于以下位置:
/tmp/my_python_lib/lib64/python3.6,
/tmp/my_python_lib/lib/python3.6
将这些包与您的脚本文件一起压缩并上传到 S3,可以在压缩根文件夹的 lambda.Instead 中访问您必须 select 所有文件并压缩它或发送到压缩文件夹。
其他提示:
如果要将所有包安装在一个目录下,可以使用命令:
pip install --upgrade --target=/tmp/my_python_lib/lib/python3.6/dist-packages pandas
截至 2018 年 8 月,最简单的方法可能是开始 new AWS Cloud9 environment。
然后在环境中创建一个 Lambda 函数。接下来运行这个进入Cloud9命令行:
cd YourApplicationName
/venv/bin/pip install scipy -t .
/venv/bin/pip install numpy -t .
/venv/bin/pip install moviepy -t .
现在我可以在 lambda_handler 函数中导入模块了。
2018 年 11 月。嗨,朋友们,这个 post 对我非常有帮助。但是,到目前为止,答案并不是很自动化。我在此处 https://gist.github.com/steinwaywhw/6a6a25d594cc07146c60af943f74c16f 编写了一个 Python 脚本和教程,以在 EC2 上使用 pip
和 virtualenv
自动创建已编译的 Python 包。一切都是 Python (Boto3),没有 bash 脚本,没有 Web 控制台,没有 awscli
。
除了自动化之外还有一个变化,我认为这是一个改进。我从 EC2 下载了整个 Python 虚拟环境,保留了它的文件夹结构,而不是将 lib
和 lib64
包合并在一起。我永远不明白合并这两个文件夹的预期含义。如果某些包覆盖了其他包怎么办,对吗?此外,伪造一个官方虚拟环境仍然比自己动手更安全。
为了使下载的虚拟环境正常工作,Lambda 函数的源代码添加了一些样板代码以使用 sys.path
更新 Python 搜索路径。 Python 虚拟环境的预期 sys.path
可以通过
找到
- 在你自己的机器上,创建一个虚拟环境并激活它。
- 运行 在此虚拟环境中执行 Python 脚本并在
import sys
之后执行 print(sys.path)
。
您可以从那里开始并根据需要进行修改。
为了加载 numpy
和我打包的虚拟环境中的其他包,为 Lambda 函数添加的样板代码片段粘贴在下面。在我的例子中,我加载了依赖于 numpy
的 pandas_datareader
。
import os
import sys
# https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html
workdir = os.getenv('LAMBDA_TASK_ROOT')
version = f'{sys.version_info[0]}.{sys.version_info[1]}'
additionals = [f'{workdir}/venv/lib64/python{version}/site-packages',
f'{workdir}/venv/lib64/python{version}/lib-dynload',
f'{workdir}/venv/lib64/python{version}/dist-packages',
f'{workdir}/venv/lib/python{version}/dist-packages',
f'{workdir}/venv/lib/python{version}/site-packages']
sys.path = additionals + sys.path
import pandas_datareader as pdr
您可以使用 scipy、numpy、moviepy 和 pandas 在任何 OS 上为 lambda 创建 zip 文件。
https://pypi.org/project/scipy/#files
pypi 有不同 OS 的 wheel 文件,你可以下载 manylinux whl 文件并解压。之后删除 dist-info 和 pyc 文件并全部压缩。
然后可以将最终的 zip 文件上传到 S3 并转换为 lambda 层。
This教程有助于深入理解
我想使用 AWS Lambda
功能生成视频。
我现在有以下过程来构建我的 Lambda
函数:
第 1 步
触发一个 Amazon Linux EC2
实例并 运行 以 root 身份运行它:
#! /usr/bin/env bash
# Install the SciPy stack on Amazon Linux and prepare it for AWS Lambda
yum -y update
yum -y groupinstall "Development Tools"
yum -y install blas --enablerepo=epel
yum -y install lapack --enablerepo=epel
yum -y install atlas-sse3-devel --enablerepo=epel
yum -y install Cython --enablerepo=epel
yum -y install python27
yum -y install python27-numpy.x86_64
yum -y install python27-numpy-f2py.x86_64
yum -y install python27-scipy.x86_64
/usr/local/bin/pip install --upgrade pip
mkdir -p /home/ec2-user/stack
/usr/local/bin/pip install moviepy -t /home/ec2-user/stack
cp -R /usr/lib64/python2.7/dist-packages/numpy /home/ec2-user/stack/numpy
cp -R /usr/lib64/python2.7/dist-packages/scipy /home/ec2-user/stack/scipy
tar -czvf stack.tgz /home/ec2-user/stack/*
第 2 步
我将生成的 tarball scp 到我的笔记本电脑。然后 运行 这个脚本来构建一个 zip 存档。
#! /usr/bin/env bash
mkdir tmp
rm lambda.zip
tar -xzf stack.tgz -C tmp
zip -9 lambda.zip process_movie.py
zip -r9 lambda.zip *.ttf
cd tmp/home/ec2-user/stack/
zip -r9 ../../../../lambda.zip *
process_movie.py
脚本目前只是测试堆栈是否正常:
def make_movie(event, context):
import os
print(os.listdir('.'))
print(os.listdir('numpy'))
try:
import scipy
except ImportError:
print('can not import scipy')
try:
import numpy
except ImportError:
print('can not import numpy')
try:
import moviepy
except ImportError:
print('can not import moviepy')
第 3 步
然后我将生成的存档上传到 S3 作为我的 lambda
函数的来源。
当我测试该功能时,我得到以下 callstack
:
START RequestId: 36c62b93-b94f-11e5-9da7-83f24fc4b7ca Version: $LATEST
['tqdm', 'imageio-1.4.egg-info', 'decorator.pyc', 'process_movie.py', 'decorator-4.0.6.dist-info', 'imageio', 'moviepy', 'tqdm-3.4.0.dist-info', 'scipy', 'numpy', 'OpenSans-Regular.ttf', 'decorator.py', 'moviepy-0.2.2.11.egg-info']
['add_newdocs.pyo', 'numarray', '__init__.py', '__config__.pyc', '_import_tools.py', 'setup.pyo', '_import_tools.pyc', 'doc', 'setupscons.py', '__init__.pyc', 'setup.py', 'version.py', 'add_newdocs.py', 'random', 'dual.pyo', 'version.pyo', 'ctypeslib.pyc', 'version.pyc', 'testing', 'dual.pyc', 'polynomial', '__config__.pyo', 'f2py', 'core', 'linalg', 'distutils', 'matlib.pyo', 'tests', 'matlib.pyc', 'setupscons.pyc', 'setup.pyc', 'ctypeslib.py', 'numpy', '__config__.py', 'matrixlib', 'dual.py', 'lib', 'ma', '_import_tools.pyo', 'ctypeslib.pyo', 'add_newdocs.pyc', 'fft', 'matlib.py', 'setupscons.pyo', '__init__.pyo', 'oldnumeric', 'compat']
can not import scipy
'module' object has no attribute 'core': AttributeError
Traceback (most recent call last):
File "/var/task/process_movie.py", line 91, in make_movie
import numpy
File "/var/task/numpy/__init__.py", line 122, in <module>
from numpy.__config__ import show as show_config
File "/var/task/numpy/numpy/__init__.py", line 137, in <module>
import add_newdocs
File "/var/task/numpy/numpy/add_newdocs.py", line 9, in <module>
from numpy.lib import add_newdoc
File "/var/task/numpy/lib/__init__.py", line 13, in <module>
from polynomial import *
File "/var/task/numpy/lib/polynomial.py", line 11, in <module>
import numpy.core.numeric as NX
AttributeError: 'module' object has no attribute 'core'
END RequestId: 36c62b93-b94f-11e5-9da7-83f24fc4b7ca
REPORT RequestId: 36c62b93-b94f-11e5-9da7-83f24fc4b7ca Duration: 112.49 ms Billed Duration: 200 ms Memory Size: 1536 MB Max Memory Used: 14 MB
我不明白为什么 python 找不到文件夹结构中存在的核心目录。
编辑:
按照@jarmod 的建议,我将 lambda
函数缩减为:
def make_movie(event, context):
print('running make movie')
import numpy
我现在有以下错误:
START RequestId: 6abd7ef6-b9de-11e5-8aee-918ac0a06113 Version: $LATEST
running make movie
Error importing numpy: you should not try to import numpy from
its source directory; please exit the numpy source tree, and relaunch
your python intepreter from there.: ImportError
Traceback (most recent call last):
File "/var/task/process_movie.py", line 3, in make_movie
import numpy
File "/var/task/numpy/__init__.py", line 127, in <module>
raise ImportError(msg)
ImportError: Error importing numpy: you should not try to import numpy from
its source directory; please exit the numpy source tree, and relaunch
your python intepreter from there.
END RequestId: 6abd7ef6-b9de-11e5-8aee-918ac0a06113
REPORT RequestId: 6abd7ef6-b9de-11e5-8aee-918ac0a06113 Duration: 105.95 ms Billed Duration: 200 ms Memory Size: 1536 MB Max Memory Used: 14 MB
我也在关注你的第一个 link 并设法在 Lambda 中导入 numpy 和 pandas以这种方式运行(在 Windows 上):
- 使用 64 位 Amazon Linux AMI 2015.09.1 启动了 (free-tier) t2.micro EC2 instance 并使用Putty 到 SSH 中。
尝试了与您使用的相同命令以及亚马逊文章推荐的命令:
sudo yum -y update sudo yum -y upgrade sudo yum -y groupinstall "Development Tools" sudo yum -y install blas --enablerepo=epel sudo yum -y install lapack --enablerepo=epel sudo yum -y install Cython --enablerepo=epel sudo yum install python27-devel python27-pip gcc
创建了虚拟环境:
virtualenv ~/env source ~/env/bin/activate
安装了 软件包:
sudo ~/env/bin/pip2.7 install numpy sudo ~/env/bin/pip2.7 install pandas
然后,我使用 WinSCP 登录并下载所有内容(_markerlib、pip*、pkg_resources、setuptools* 和 easyinstall* 除外)来自
/home/ec2-user/env/lib/python2.7/dist-packages
,以及来自/home/ec2-user/env/lib64/python2.7/site-packages
的所有内容来自 EC2 实例。我将所有这些文件夹和文件与包含 Lambda 函数的 .py 文件一起放入一个 zip 中。 illustration of all files copied
因为这个 .zip 大于 10 MB,所以我创建了一个 S3 存储桶 来存储文件。我从那里复制了文件的 link 并粘贴到 Lambda 函数的 "Upload a .ZIP from Amazon S3"。
EC2实例可以关闭,不再需要了。
有了这个,我可以导入 numpy 和 pandas。我不熟悉 moviepy,但 scipy 可能已经很棘手了,因为 Lambda 有一个 limit 解压缩部署包大小为 262 144 000 字节。恐怕 numpy 和 scipy 一起已经结束了。
在此线程中的所有帖子的帮助下,这里是记录的解决方案:
要使其正常工作,您需要:
用至少 2GO RAM 启动一个
EC2
实例(以便能够编译NumPy
&SciPy
)安装所需的依赖项
sudo yum -y update sudo yum -y upgrade sudo yum -y groupinstall "Development Tools" sudo yum -y install blas --enablerepo=epel sudo yum -y install lapack --enablerepo=epel sudo yum -y install Cython --enablerepo=epel sudo yum install python27-devel python27-pip gcc virtualenv ~/env source ~/env/bin/activate pip install scipy pip install numpy pip install moviepy
将
stack
文件夹中目录(_markerlib、pip*、pkg_resources、setuptools* 和 easyinstall* 除外)的所有内容复制到您的语言环境机器:home/ec2-user/env/lib/python2.7/dist-packages
home/ec2-user/env/lib64/python2.7/dist-packages
从您那里获取所有需要的共享库
EC2
实例:libatlas.so.3
libf77blas.so.3
liblapack.so.3
libptf77blas.so.3
libcblas.so.3
libgfortran.so.3
libptcblas.so.3
libquadmath.so.0
将它们放在
stack
文件夹的lib
子文件夹中imageio
是moviepy
的依赖项,您需要下载其依赖项的一些二进制版本:libfreeimage
和ffmpeg
;可以找到它们 here。将它们放在堆栈文件夹的根目录下,并将libfreeimage-3.16.0-linux64.so
重命名为libfreeimage.so
您现在应该有一个
stack
文件夹,其中包含:- 所有 python 根依赖关系
lib
子文件夹中的所有共享库ffmpeg
根目录下的二进制文件libfreeimage.so
在根目录
压缩此文件夹:
zip -r9 stack.zip . -x ".*" -x "*/.*"
使用以下
的入口点lambda_function.py
作为您的lambda
from __future__ import print_function import os import subprocess SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) LIB_DIR = os.path.join(SCRIPT_DIR, 'lib') FFMPEG_BINARY = os.path.join(SCRIPT_DIR, 'ffmpeg') def lambda_handler(event, context): command = 'LD_LIBRARY_PATH={} IMAGEIO_FFMPEG_EXE={} python movie_maker.py'.format( LIB_DIR, FFMPEG_BINARY, ) try: output = subprocess.check_output(command, shell=True) print(output) except subprocess.CalledProcessError as e: print(e.output)
写一个
movie_maker.py
脚本依赖于moviepy
,numpy
, ...将这些脚本添加到您的 stack.zip 文件
zip -r9 lambda.zip *.py
将 zip 上传到
S3
并将其用作您的lambda
的来源
您还可以下载 stack.zip
here.
这里的帖子帮助我找到了一种使用可包含在 AWS Lambda 部署包中的库文件静态编译 NumPy 的方法。此解决方案不像@rouk1 解决方案那样依赖于 LD_LIBRARY_PATH 值。
编译好的NumPy库可以从https://github.com/vitolimandibhrata/aws-lambda-numpy
下载这里是自定义编译NumPy的步骤
从头开始编译这个包的说明
使用 AWS Linux.
准备一个新的 AWS EC 实例安装编译器依赖项
sudo yum -y install python-devel
sudo yum -y install gcc-c++
sudo yum -y install gcc-gfortran
sudo yum -y install libgfortran
安装 NumPy 依赖项
sudo yum -y install blas
sudo yum -y install lapack
sudo yum -y install atlas-sse3-devel
创建 /var/task/lib 以包含运行时库
mkdir -p /var/task/lib
/var/task 是您的代码将驻留在 AWS Lambda 中的根目录,因此我们需要将所需的库文件静态 link 在一个众所周知的文件夹中,在本例中为 /var/task/lib
将以下库文件复制到/var/task/lib
cp /usr/lib64/atlas-sse3/liblapack.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libptf77blas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libf77blas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libptcblas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libcblas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libatlas.so.3 /var/task/lib/.
cp /usr/lib64/atlas-sse3/libptf77blas.so.3 /var/task/lib/.
cp /usr/lib64/libgfortran.so.3 /var/task/lib/.
cp /usr/lib64/libquadmath.so.0 /var/task/lib/.
从http://sourceforge.net/projects/numpy/files/NumPy/
获取最新的numpy源代码转到 numpy 源代码文件夹,例如 numpy-1.10.4 使用以下条目创建一个 site.cfg 文件
[atlas]
libraries=lapack,f77blas,cblas,atlas
search_static_first=true
runtime_library_dirs = /var/task/lib
extra_link_args = -lgfortran -lquadmath
-lgfortran -lquadmath 标志需要静态 link gfortran 和 quadmath 库以及 runtime_library_dirs
中定义的文件构建 NumPy
python setup.py build
安装 NumPy
python setup.py install
检查库是否linked到/var/task/lib
中的文件ldd $PYTHON_HOME/lib64/python2.7/site-packages/numpy/linalg/lapack_lite.so
你应该看看
linux-vdso.so.1 => (0x00007ffe0dd2d000)
liblapack.so.3 => /var/task/lib/liblapack.so.3 (0x00007ffad6be5000)
libptf77blas.so.3 => /var/task/lib/libptf77blas.so.3 (0x00007ffad69c7000)
libptcblas.so.3 => /var/task/lib/libptcblas.so.3 (0x00007ffad67a7000)
libatlas.so.3 => /var/task/lib/libatlas.so.3 (0x00007ffad6174000)
libf77blas.so.3 => /var/task/lib/libf77blas.so.3 (0x00007ffad5f56000)
libcblas.so.3 => /var/task/lib/libcblas.so.3 (0x00007ffad5d36000)
libpython2.7.so.1.0 => /usr/lib64/libpython2.7.so.1.0 (0x00007ffad596d000)
libgfortran.so.3 => /var/task/lib/libgfortran.so.3 (0x00007ffad5654000)
libm.so.6 => /lib64/libm.so.6 (0x00007ffad5352000)
libquadmath.so.0 => /var/task/lib/libquadmath.so.0 (0x00007ffad5117000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ffad4f00000)
libc.so.6 => /lib64/libc.so.6 (0x00007ffad4b3e000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ffad4922000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007ffad471d000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007ffad451a000)
/lib64/ld-linux-x86-64.so.2 (0x000055cfc3ab8000)
我喜欢@Vito Limandibhrata 的回答,但我认为在 numpy==1.11.1 中使用 runtime_library_dirs 构建 numpy 是不够的。如果有人认为 site-cfg 被忽略,请执行以下操作:
cp /usr/lib64/atlas-sse3/*.a /var/task/lib/
*.a 需要atlas-sse3 下的文件来构建numpy。此外,您可能需要 运行 以下内容:
python setup.py config
检查 numpy 配置。如果需要更多信息,您将看到以下消息:
atlas_threads_info:
Setting PTATLAS=ATLAS libraries ptf77blas,ptcblas,atlas not found in /root/Envs/skl/lib
libraries lapack_atlas not found in /root/Envs/skl/lib
libraries ptf77blas,ptcblas,atlas not found in /usr/local/lib64
libraries lapack_atlas not found in /usr/local/lib64
libraries ptf77blas,ptcblas,atlas not found in /usr/local/lib
libraries lapack_atlas not found in /usr/local/lib
libraries lapack_atlas not found in /usr/lib64/atlas-sse3
<class 'numpy.distutils.system_info.atlas_threads_info'>
Setting PTATLAS=ATLAS
Setting PTATLAS=ATLAS
Setting PTATLAS=ATLAS
Setting PTATLAS=ATLAS
libraries lapack not found in ['/var/task/lib']
Runtime library lapack was not found. Ignoring
libraries f77blas not found in ['/var/task/lib']
Runtime library f77blas was not found. Ignoring
libraries cblas not found in ['/var/task/lib']
Runtime library cblas was not found. Ignoring
libraries atlas not found in ['/var/task/lib']
Runtime library atlas was not found. Ignoring
FOUND:
extra_link_args = ['-lgfortran -lquadmath']
define_macros = [('NO_ATLAS_INFO', -1)]
language = f77
libraries = ['lapack', 'ptf77blas', 'ptcblas', 'atlas', 'lapack', 'f77blas', 'cblas', 'atlas']
library_dirs = ['/usr/lib64/atlas-sse3']
include_dirs = ['/usr/include']
然后 site-cfg 将被忽略。
提示:如果使用pip构建numpy runtime_library_dirs,最好创建~/.numpy-site.cfg
并添加以下内容:
[atlas]
libraries = lapack,f77blas,cblas,atlas
search_static_first = true
runtime_library_dirs = /var/task/lib
extra_link_args = -lgfortran -lquadmath
然后 numpy 识别 .numpy-site.cfg 文件。这是非常简单易行的方法。
另一种非常简单的方法是使用 LambCI 为模仿 Lambda 而制作的很棒的 docker 容器进行构建:https://github.com/lambci/docker-lambda
lambci/lambda:build
容器类似于 AWS Lambda,但增加了 mostly-complete 构建环境。要在其中启动 shell 会话:
docker run -v "$PWD":/var/task -it lambci/lambda:build bash
会话内部:
export share=/var/task
easy_install pip
pip install -t $share numpy
或者,使用 virtualenv:
export share=/var/task
export PS1="[\u@\h:\w]$ " # required by virtualenv
easy_install pip
pip install virtualenv
# ... make the venv, install numpy, and copy it to $share
稍后您可以使用 lambci/lambda 主容器来测试您的构建。
截至 2017 年,NumPy 和 SciPy 具有可在 Lambda 上运行的轮子(这些包包括预编译的 libgfortran
和 libopenblas
)。
据我所知,MoviePy 是一个纯粹的 Python 模块,所以基本上你可以这样做:
pip2 install -t lambda moviepy scipy
然后将您的处理程序复制到 lambda
目录并压缩。除了,您很可能会超过 50/250 MB 的大小限制。有几件事可以提供帮助:
- 删除.pycs、文档、测试和其他不需要的部分;
- 保留 NumPy 和 SciPy 公共库的单个副本;
- 剥离不必要的库,例如调试符号;
- 使用更高的设置压缩存档。
这里有一个例子script,可以自动执行上述几点。
我可以确认@attila-tanyi 发布的步骤在 Amazon Linux 下可以正常工作。我只想补充一点,不需要使用 EC2,因为默认存储库中有一个 Amazon Linux docker 容器可用。
docker pull amazonlinux && docker run -it amazonlinux
# Follow @attila-tanyi steps
# Note - sudo is not necessary here
我使用应用程序中嵌入的 Dockerfile 来构建和部署到 Lambda。
截至 2018 年,在 AWS EC2 Python3 中安装外部模块的步骤:
在 Amazon Linux AMI 201709 上启动 EC2。
使用私钥和 public 密钥通过 putty ssh 并成为超级用户。
安装Python 3 并创建虚拟环境,然后将其设为默认值
yum install python36 python36-virtualenv python36-pip virtualenv -p python3.6 /tmp/my_python_lib source /tmp/my_python_lib/bin/activate which python --to check which version s installed pip3 install numpy
使用winscp将站点包和dist包下的文件复制到本地机器中。
要查找实际位置,请使用 grep 命令 ---
grep -r dist-packages *.
这些包可能在 lib 和 lib64 中。
站点和 dist 包将位于以下位置:
/tmp/my_python_lib/lib64/python3.6, /tmp/my_python_lib/lib/python3.6
将这些包与您的脚本文件一起压缩并上传到 S3,可以在压缩根文件夹的 lambda.Instead 中访问您必须 select 所有文件并压缩它或发送到压缩文件夹。
其他提示:
如果要将所有包安装在一个目录下,可以使用命令:
pip install --upgrade --target=/tmp/my_python_lib/lib/python3.6/dist-packages pandas
截至 2018 年 8 月,最简单的方法可能是开始 new AWS Cloud9 environment。 然后在环境中创建一个 Lambda 函数。接下来运行这个进入Cloud9命令行:
cd YourApplicationName
/venv/bin/pip install scipy -t .
/venv/bin/pip install numpy -t .
/venv/bin/pip install moviepy -t .
现在我可以在 lambda_handler 函数中导入模块了。
2018 年 11 月。嗨,朋友们,这个 post 对我非常有帮助。但是,到目前为止,答案并不是很自动化。我在此处 https://gist.github.com/steinwaywhw/6a6a25d594cc07146c60af943f74c16f 编写了一个 Python 脚本和教程,以在 EC2 上使用 pip
和 virtualenv
自动创建已编译的 Python 包。一切都是 Python (Boto3),没有 bash 脚本,没有 Web 控制台,没有 awscli
。
除了自动化之外还有一个变化,我认为这是一个改进。我从 EC2 下载了整个 Python 虚拟环境,保留了它的文件夹结构,而不是将 lib
和 lib64
包合并在一起。我永远不明白合并这两个文件夹的预期含义。如果某些包覆盖了其他包怎么办,对吗?此外,伪造一个官方虚拟环境仍然比自己动手更安全。
为了使下载的虚拟环境正常工作,Lambda 函数的源代码添加了一些样板代码以使用 sys.path
更新 Python 搜索路径。 Python 虚拟环境的预期 sys.path
可以通过
- 在你自己的机器上,创建一个虚拟环境并激活它。
- 运行 在此虚拟环境中执行 Python 脚本并在
import sys
之后执行print(sys.path)
。 您可以从那里开始并根据需要进行修改。
为了加载 numpy
和我打包的虚拟环境中的其他包,为 Lambda 函数添加的样板代码片段粘贴在下面。在我的例子中,我加载了依赖于 numpy
的 pandas_datareader
。
import os
import sys
# https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html
workdir = os.getenv('LAMBDA_TASK_ROOT')
version = f'{sys.version_info[0]}.{sys.version_info[1]}'
additionals = [f'{workdir}/venv/lib64/python{version}/site-packages',
f'{workdir}/venv/lib64/python{version}/lib-dynload',
f'{workdir}/venv/lib64/python{version}/dist-packages',
f'{workdir}/venv/lib/python{version}/dist-packages',
f'{workdir}/venv/lib/python{version}/site-packages']
sys.path = additionals + sys.path
import pandas_datareader as pdr
您可以使用 scipy、numpy、moviepy 和 pandas 在任何 OS 上为 lambda 创建 zip 文件。
https://pypi.org/project/scipy/#files
pypi 有不同 OS 的 wheel 文件,你可以下载 manylinux whl 文件并解压。之后删除 dist-info 和 pyc 文件并全部压缩。 然后可以将最终的 zip 文件上传到 S3 并转换为 lambda 层。
This教程有助于深入理解