I'd like to generate video using AWS Lambda
feature.
I've followed instructions found here and here.
And I now have the following process to build my Lambda
function:
Step 1
Fire a Amazon Linux EC2
instance and run this as root on it:
#! /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/*
Step 2
I scp the resulting tarball to my laptop. And then run this script to build a zip archive.
#! /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
script is at the moment only a test to see if the stack is ok:
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')
Step 3
Then I upload the resulting archive to S3 to be the source of my lambda
function.
When I test the function I get the following 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
I cant understand why python does not found the core directory that is present in the folder structure.
EDIT:
Following @jarmod advice I've reduced the lambda
function to:
def make_movie(event, context):
print('running make movie')
import numpy
I now have the following error:
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
I was also following your first link and managed to import numpy and pandas in a Lambda function this way (on Windows):
Tried the same commands you used and the one recommended by the Amazon article:
Created the virtual environment:
Installed the packages:
Then, using WinSCP, I logged in and downloaded everything (except _markerlib, pip*, pkg_resources, setuptools* and easyinstall*) from
/home/ec2-user/env/lib/python2.7/dist-packages
, and everything from/home/ec2-user/env/lib64/python2.7/site-packages
from the EC2 instance.I put all these folders and files into one zip, along with the .py file containing the Lambda function. illustration of all files copied
Because this .zip is larger than 10 MB, I created an S3 bucket to store the file. I copied the link of the file from there and pasted at "Upload a .ZIP from Amazon S3" at the Lambda function.
The EC2 instance can be shut down, it's not needed any more.
With this, I could import numpy and pandas. I'm not familiar with moviepy, but scipy might already be tricky as Lambda has a limit for unzipped deployment package size at 262 144 000 bytes. I'm afraid numpy and scipy together are already over that.
As of 2018, Steps to install external modules in Python3 on AWS EC2:
Launch EC2 on Amazon Linux AMI 201709.
ssh with putty using private and public key and become super user.
Install Python 3 and create virtual env, then make it default
Copy files under site packages and dist packages into your local machhine using winscp.
To find actual location use grep commands ---
These packages could be inside both lib and lib64.
Site and dist packages will be under location:
Zip these packages along with your script file and upload to S3 which can be accessed in lambda.Instead of zipping the root folder you have to select all files and zip it or send to compressed folder.
Additional tips:
If you want to install all packages under one directory, you can use command:
Another, very simple method that's possible these days is to build using the awesome docker containers that LambCI made to mimic Lambda: https://github.com/lambci/docker-lambda
The
lambci/lambda:build
container resembles AWS Lambda with the addition of a mostly-complete build environment. To start a shell session in it:Inside the session:
Or, with virtualenv:
Later on you can use the main lambci/lambda container to test your build.
With the help of all posts in this thread here is a solution for the records:
To get this to work you'll need to:
start a
EC2
instance with at least 2GO RAM (to be able to compileNumPy
&SciPy
)Install the needed dependencies
Copy to your locale machine all the content of the directories (except _markerlib, pip*, pkg_resources, setuptools* and easyinstall*) in a
stack
folder:home/ec2-user/env/lib/python2.7/dist-packages
home/ec2-user/env/lib64/python2.7/dist-packages
get all required shared libraries from you
EC2
instance:libatlas.so.3
libf77blas.so.3
liblapack.so.3
libptf77blas.so.3
libcblas.so.3
libgfortran.so.3
libptcblas.so.3
libquadmath.so.0
Put them in a
lib
subfolder of thestack
folderimageio
is a dependency ofmoviepy
, you'll need to download some binary version of its dependencies:libfreeimage
and offfmpeg
; they can be found here. Put them at the root of your stack folder and renamelibfreeimage-3.16.0-linux64.so
tolibfreeimage.so
You should now have a
stack
folder containing:lib
subfolderffmpeg
binary at rootlibfreeimage.so
at rootZip this folder:
zip -r9 stack.zip . -x ".*" -x "*/.*"
Use the following
lambda_function.py
as an entry point for yourlambda
write a
movie_maker.py
script that depends onmoviepy
,numpy
, ...add those to script to your stack.zip file
zip -r9 lambda.zip *.py
upload the zip to
S3
and use it as a source for yourlambda
You can also download the
stack.zip
here.The posts here help me to find a way to statically compile NumPy with libraries files that can be included in the AWS Lambda Deployment package. This solution does not depend on LD_LIBRARY_PATH value as in @rouk1 solution.
The compiled NumPy library can be downloaded from https://github.com/vitolimandibhrata/aws-lambda-numpy
Here are the steps to custom compile NumPy
Instructions on compiling this package from scratch
Prepare a fresh AWS EC instance with AWS Linux.
Install compiler dependencies
Install NumPy dependencies
Create /var/task/lib to contain the runtime libraries
/var/task is the root directory where your code will reside in AWS Lambda thus we need to statically link the required library files in a well known folder which in this case /var/task/lib
Copy the following library files to the /var/task/lib
Get the latest numpy source code from http://sourceforge.net/projects/numpy/files/NumPy/
Go to the numpy source code folder e.g numpy-1.10.4 Create a site.cfg file with the following entries
-lgfortran -lquadmath flags are required to statically link gfortran and quadmath libraries with files defined in runtime_library_dirs
Build NumPy
Install NumPy
Check whether the libraries are linked to the files in /var/task/lib
You should see
As of 2017, NumPy and SciPy have wheels that work on Lambda (the packages include precompiled
libgfortran
andlibopenblas
). As far as I know, MoviePy is a pure Python module, so basically you could do:Then copy your handler into the
lambda
directory and zip it. Except, that you'll most likely exceed the 50/250 MB size limits. There are a couple of things that can help:Here's an example script that automates the above points.