Usando Moviepy, Scipy y Numpy en Amazon Lambda

Me gustaría generar video usando la función de AWS Lambda .

He seguido las instrucciones encontradas aquí y aquí .

Y ahora tengo el siguiente proceso para construir mi función Lambda :

Paso 1

Inicie una instancia de Amazon Linux EC2 y ejecute esto como root en ella:

 #! /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/* 

Paso 2

Yo scp el tarball resultante a mi computadora portátil. Y luego ejecute este script para construir un archivo 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 script process_movie.py es en este momento solo una prueba para ver si la stack está bien:

 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') 

Paso 3

Luego subo el archivo resultante a S3 para que sea la fuente de mi función lambda . Cuando callstack la función obtengo la siguiente 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  from numpy.__config__ import show as show_config File "/var/task/numpy/numpy/__init__.py", line 137, in  import add_newdocs File "/var/task/numpy/numpy/add_newdocs.py", line 9, in  from numpy.lib import add_newdoc File "/var/task/numpy/lib/__init__.py", line 13, in  from polynomial import * File "/var/task/numpy/lib/polynomial.py", line 11, in  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 

No puedo entender por qué Python no encuentra el directorio central que está presente en la estructura de carpetas.

EDITAR:

Siguiendo los consejos de @jarmod, he reducido la función lambda a:

 def make_movie(event, context): print('running make movie') import numpy 

Ahora tengo el siguiente 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  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 

También estaba siguiendo tu primer enlace y logré importar números y pandas en una función Lambda de esta manera (en Windows):

  1. Comenzó una instancia de t2.micro EC2 (nivel libre) con AMI 2015.09.1 ​​de Amazon Linux de 64 bits y usé Putty to SSH in.
  2. Probé los mismos comandos que usaste y el recomendado por el artículo de Amazon:

     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 
  3. Creado el entorno virtual :

     virtualenv ~/env source ~/env/bin/activate 
  4. Instalado los paquetes :

     sudo ~/env/bin/pip2.7 install numpy sudo ~/env/bin/pip2.7 install pandas 
  5. Luego, usando WinSCP, inicié sesión y descargué todo (excepto _markerlib, pip *, pkg_resources, setuptools * y easyinstall *) desde /home/ec2-user/env/lib/python2.7/dist-packages , y todo desde /home/ec2-user/env/lib64/python2.7/site-packages desde la instancia de EC2.

  6. Puse todas estas carpetas y archivos en un archivo zip , junto con el archivo .py que contiene la función Lambda. Ilustración de todos los archivos copiados.

  7. Debido a que este .zip es más grande que 10 MB, creé un cubo S3 para almacenar el archivo. Copié el enlace del archivo desde allí y lo pegué en “Cargar un .ZIP desde Amazon S3” en la función Lambda.

  8. La instancia de EC2 se puede cerrar , ya no es necesaria.

Con esto, podría importar numpy y pandas. No estoy familiarizado con Moviepy, pero Scipy podría ser complicado ya que Lambda tiene un límite para el tamaño del paquete de implementación descomprimido en 262 144 000 bytes. Me temo que entumecimiento y miedo juntos ya han superado eso.

Con la ayuda de todas las publicaciones en este hilo, aquí hay una solución para los registros:

Para que esto funcione, necesitarás:

  1. iniciar una instancia de EC2 con al menos 2GO RAM (para poder comstackr NumPy y SciPy )

  2. Instala las dependencias necesarias.

     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 
  3. Copie en su máquina local el contenido de los directorios (excepto _markerlib, pip *, pkg_resources, setuptools * y easyinstall *) en una carpeta de stack :

    • home/ec2-user/env/lib/python2.7/dist-packages
    • home/ec2-user/env/lib64/python2.7/dist-packages
  4. Obtenga todas las bibliotecas compartidas requeridas de su instancia de 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
  5. Póngalos en una subcarpeta lib de la carpeta de la stack

  6. imageio es una dependencia de moviepy , necesitarás descargar una versión binaria de sus dependencias: libfreeimage y de ffmpeg ; Se pueden encontrar aquí . libfreeimage-3.16.0-linux64.so en la raíz de la carpeta de su stack y cambie el nombre de libfreeimage-3.16.0-linux64.so a libfreeimage.so

  7. Ahora debería tener una carpeta de stack contiene:

    • todas las dependencias de python en la raíz
    • todas las bibliotecas compartidas en una subcarpeta lib
    • ffmpeg binario en la raíz
    • libfreeimage.so en la raíz
  8. Zip esta carpeta: zip -r9 stack.zip . -x ".*" -x "*/.*" zip -r9 stack.zip . -x ".*" -x "*/.*"

  9. Use la siguiente lambda_function.py como punto de entrada para su 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) 
  10. escribe un script movie_maker.py que dependa de la moviepy , el numpy , …

  11. agréguelos al script a su archivo zip -r9 lambda.zip *.py

  12. cargue el zip a S3 y utilícelo como fuente para su lambda

También puedes descargar el stack.zip aquí .

Las publicaciones aquí me ayudan a encontrar una manera de comstackr de forma estática NumPy con archivos de bibliotecas que se pueden incluir en el paquete de implementación de Lambda de AWS. Esta solución no depende del valor LD_LIBRARY_PATH como en la solución @ rouk1.

La biblioteca NumPy comstackda se puede descargar desde https://github.com/vitolimandibhrata/aws-lambda-numpy

Aquí están los pasos para comstackr a medida NumPy

Instrucciones para comstackr este paquete desde cero.

Prepare una nueva instancia de AWS EC con AWS Linux.

Instalar dependencias del comstackdor

 sudo yum -y install python-devel sudo yum -y install gcc-c++ sudo yum -y install gcc-gfortran sudo yum -y install libgfortran 

Instalar dependencias NumPy

 sudo yum -y install blas sudo yum -y install lapack sudo yum -y install atlas-sse3-devel 

Cree / var / task / lib para contener las bibliotecas de tiempo de ejecución

 mkdir -p /var/task/lib 

/ var / task es el directorio raíz donde residirá su código en AWS Lambda, por lo que necesitamos vincular estáticamente los archivos de biblioteca necesarios en una carpeta bien conocida que en este caso / var / task / lib

Copie los siguientes archivos de biblioteca en / 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/. 

Obtenga el último código fuente numpy de http://sourceforge.net/projects/numpy/files/NumPy/

Vaya a la carpeta del código fuente de Numpy, por ejemplo, numpy-1.10.4 Cree un archivo site.cfg con las siguientes entradas

 [atlas] libraries=lapack,f77blas,cblas,atlas search_static_first=true runtime_library_dirs = /var/task/lib extra_link_args = -lgfortran -lquadmath 

-lgfortran -lquadmath flags son necesarias para vincular estáticamente las bibliotecas gfortran y quadmath con archivos definidos en runtime_library_dirs

Construir NumPy

 python setup.py build 

Instala NumPy

 python setup.py install 

Compruebe si las bibliotecas están vinculadas a los archivos en / var / task / lib

 ldd $PYTHON_HOME/lib64/python2.7/site-packages/numpy/linalg/lapack_lite.so 

Debería ver

 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) 

Otro método muy simple que es posible en estos días es construir utilizando los asombrosos contenedores docker que LambCI creó para imitar a Lambda: https://github.com/lambci/docker-lambda

El lambci/lambda:build asemeja a AWS Lambda con la adición de un entorno de construcción en su mayoría completo. Para iniciar una sesión de shell en ella:

 docker run -v "$PWD":/var/task -it lambci/lambda:build bash 

Dentro de la sesión:

 export share=/var/task easy_install pip pip install -t $share numpy 

O, con 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 

Más adelante, puede utilizar el contenedor principal lambci / lambda para probar su construcción.

A partir de 2017, NumPy y SciPy tienen ruedas que funcionan en Lambda (los paquetes incluyen libgfortran y libopenblas precomstackdos). Por lo que sé, MoviePy es un módulo de Python puro, así que básicamente podrías hacer:

 pip2 install -t lambda moviepy scipy 

Luego copie su controlador en el directorio lambda y comprímalo. Excepto que lo más probable es que exceda los límites de tamaño de 50/250 MB. Hay un par de cosas que pueden ayudar:

  • eliminar .pycs, documentos, pruebas y otras partes innecesarias;
  • deje una sola copia de las bibliotecas comunes de NumPy y SciPy;
  • Las bibliotecas de bandas de piezas no esenciales, como los símbolos de depuración;
  • Comprime el archivo usando configuraciones más altas.

Aquí hay un script de ejemplo que automatiza los puntos anteriores.

A partir de 2018, Pasos para instalar módulos externos en Python3 en AWS EC2:

  1. Lanzamiento de EC2 en Amazon Linux AMI 201709.

  2. ssh con masilla usando clave pública y privada y conviértase en superusuario.

  3. Instala Python 3 y crea env virtual, luego hazlo por defecto

     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 
  4. Copie los archivos de los paquetes del sitio y los paquetes de dist en su máquina local usando winscp.

    Para encontrar la ubicación real use los comandos grep —

      grep -r dist-packages *. 

Estos paquetes podrían estar dentro de lib y lib64.

  1. Los paquetes de sitio y dist estarán debajo de la ubicación:

     /tmp/my_python_lib/lib64/python3.6, /tmp/my_python_lib/lib/python3.6 
  2. Comprima estos paquetes junto con su archivo de script y cárguelo en S3, al que se puede acceder en lambda. En lugar de comprimir la carpeta raíz, debe seleccionar todos los archivos y comprimirlos o enviarlos a una carpeta comprimida.

Consejos adicionales:

  1. Si desea instalar todos los paquetes en un directorio, puede usar el comando:

      pip install --upgrade --target=/tmp/my_python_lib/lib/python3.6/dist-packages pandas 

A partir de agosto de 2018, probablemente la forma más sencilla es iniciar un nuevo entorno AWS Cloud9 . Luego crea una función Lambda dentro del entorno. A continuación, ejecute esto en la línea de comandos de Cloud9:

  cd YourApplicationName /venv/bin/pip install scipy -t . /venv/bin/pip install numpy -t . /venv/bin/pip install moviepy -t . 

Ahora puedo importar los módulos en la función lambda_handler.

Nov 2018 . Hola amigos, este post es extremadamente útil para mí. Sin embargo, las respuestas hasta ahora no son muy automatizadas. Escribí un script y tutorial de Python aquí https://gist.github.com/steinwaywhw/6a6a25d594cc07146c60af943f74c16f para automatizar la creación de paquetes comstackdos de Python usando pip y virtualenv en EC2. Todo es Python (Boto3), sin script bash, sin consola web, sin awscli .

Hay otro cambio además de la automatización, que creo que es una mejora. Descargué todo el entorno virtual de Python desde EC2 conservando sus estructuras de carpetas, en lugar de fusionar los paquetes lib y lib64 todos juntos. Nunca entiendo el significado pretendido de fusionar esas dos carpetas. ¿Qué pasa si algunos paquetes anulan otros paquetes, verdad? Además, la falsificación de un entorno virtual oficial es una forma segura de hacerlo que rodar el suyo.

Para que el entorno virtual descargado funcione, el código fuente de la función Lambda agrega algo de código repetitivo para actualizar la ruta de búsqueda de Python utilizando sys.path . El sys.path deseado de un entorno virtual Python se puede encontrar por

  • En su propia máquina, cree un entorno virtual y actívelo.
  • Ejecute un script de Python en este entorno virtual e print(sys.path) después de import sys . Puedes empezar desde allí y modificarlo como mejor te parezca.

A continuación se pega un fragmento del código repetitivo que se agrega a la función Lambda para cargar numpy y otros paquetes de mi entorno virtual empaquetado. En mi caso, pandas_datareader que se basa en numpy .

 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 

Puedo confirmar que los pasos publicados por @ attila-tanyi funcionan correctamente en Amazon Linux. Solo agregaría que no hay necesidad de usar un EC2, ya que hay un contenedor docker de Amazon Linux disponible desde el repository predeterminado.

 docker pull amazonlinux && docker run -it amazonlinux # Follow @attila-tanyi steps # Note - sudo is not necessary here 

Utilizo el Dockerfile integrado en mi aplicación para comstackr e implementar en Lambda.

Me gusta la respuesta de @Vito Limandibhrata, pero creo que no es suficiente construir numpy con runtime_library_dirs en numpy == 1.11.1. Si alguien piensa que se ignora site-cfg, haga lo siguiente:

 cp /usr/lib64/atlas-sse3/*.a /var/task/lib/ 

Los archivos * .a bajo atlas-sse3 son necesarios para construir numpy. Además, es posible que necesites ejecutar lo siguiente:

 python setup.py config 

para comprobar la configuración numpy. Si requiere algo más, verá el siguiente mensaje:

 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  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'] 

entonces el sitio-cfg será ignorado.

Consejo: Si se usa pip para comstackr numpy con runtime_library_dirs, sería mejor crear ~/.numpy-site.cfg y agregar lo siguiente:

 [atlas] libraries = lapack,f77blas,cblas,atlas search_static_first = true runtime_library_dirs = /var/task/lib extra_link_args = -lgfortran -lquadmath 

entonces numpy reconoce el archivo .numpy-site.cfg. Es una forma bastante simple y fácil.