簡體   English   中英

在亞馬遜 lambda 中使用 moviepy、scipy 和 numpy

[英]Using moviepy, scipy and numpy in amazon lambda

我想使用AWS Lambda功能生成視頻。

我已按照此處此處的說明進行操作。

我現在有以下過程來構建我的Lambda function:

第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 function 的來源。當我測試 function 時,我得到以下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 function 減少為:

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

我也在關注你的第一個鏈接並設法以這種方式在Lambda函數中導入numpypandas (在Windows上):

  1. 使用64位Amazon Linux AMI 2015.09.1啟動(免費層) t2.micro EC2實例 ,並使用Putty進入SSH。
  2. 嘗試使用您使用的相同命令和亞馬遜文章推薦的命令

     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. 創建虛擬環境

     virtualenv ~/env source ~/env/bin/activate 
  4. 安裝

     sudo ~/env/bin/pip2.7 install numpy sudo ~/env/bin/pip2.7 install pandas 
  5. 然后,使用WinSCP,我從/home/ec2-user/env/lib/python2.7/dist-packages登錄並下載了所有內容(除了_markerlib,pip *,pkg_resources,setuptools *和easyinstall *),以及來自/home/ec2-user/env/lib64/python2.7/site-packages所有內容來自EC2實例的/home/ec2-user/env/lib64/python2.7/site-packages

  6. 我將所有這些文件夾和文件放在一個zip中 ,以及包含Lambda函數的.py文件。 復制的所有文件的插圖

  7. 因為這個.zip大於10 MB,所以我創建了一個S3存儲桶來存儲文件。 我從那里復制了文件的鏈接並粘貼在Lambda函數的“從Amazon S3上傳一個.ZIP”。

  8. 可以關閉 EC2實例,不再需要它。

有了這個,我可以導入numpy和pandas。 我不熟悉moviepy,但scipy可能已經很棘手,因為Lambda對解壓縮的部署包大小限制為262 144 000字節。 我害怕numpy和scipy已經結束了。

在這個帖子的所有帖子的幫助下,這里是記錄的解決方案:

要實現這一點,您需要:

  1. 使用至少2GO RAM啟動EC2實例(以便能夠編譯NumPySciPy

  2. 安裝所需的依賴項

     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. 復制到您的語言環境的機器目錄的所有內容(除_markerlib,PIP *,通過pkg_resources,setuptools的*和* easyinstall)在stack的文件夾:

    • home/ec2-user/env/lib/python2.7/dist-packages
    • home/ec2-user/env/lib64/python2.7/dist-packages
  4. 從您的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. 將它們放在stack文件夾的lib子文件夾中

  6. imageioimageio的依賴moviepy ,你需要下載它的依賴項的一些二進制版本: libfreeimageffmpeg ; 他們可以在這里找到。 將它們放在堆棧文件夾的根目錄下,並將libfreeimage-3.16.0-linux64.so重命名為libfreeimage.so

  7. 您現在應該有一個stack文件夾包含:

    • root的所有python依賴項
    • lib子文件夾中的所有共享庫
    • 根目錄下的ffmpeg二進制文件
    • libfreeimage.so在root
  8. 壓縮此文件夾: zip -r9 stack.zip . -x ".*" -x "*/.*" zip -r9 stack.zip . -x ".*" -x "*/.*"

  9. 使用以下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) 
  10. 寫一個movie_maker.py腳本,它依賴於moviepynumpy ,...

  11. 將那些腳本添加到你的stack.zip文件zip -r9 lambda.zip *.py

  12. 將zip上傳到S3並將其用作lambda的源

你也可以在這里下載stack.zip

這里的帖子幫助我找到一種方法來靜態編譯NumPy,其中包含可以包含在AWS Lambda Deployment包中的庫文件。 此解決方案不依賴於@ 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中的根目錄,因此我們需要在一個眾所周知的文件夾中靜態鏈接所需的庫文件,在本例中為/ 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標志是將gfortran和quadmath庫與runtime_library_dirs中定義的文件靜態鏈接所必需的

建立NumPy

python setup.py build

安裝NumPy

python setup.py install

檢查庫是否鏈接到/ 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)

截至2017年,NumPy和SciPy擁有適用於Lambda的輪子(這些軟件包包括預編譯的libgfortranlibopenblas )。 據我所知,MoviePy是一個純Python模塊,所以基本上你可以這樣做:

pip2 install -t lambda moviepy scipy

然后將處理程序復制到lambda目錄並壓縮它。 除此之外,您最有可能超過50/250 MB的大小限制。 有幾件事可以幫助:

  • 刪除.pycs,docs,tests和其他不必要的部分;
  • 留下NumPy和SciPy公共圖書館的單一副本;
  • 剝離不必要的部分庫,例如調試符號;
  • 使用更高的設置壓縮存檔。

這是一個自動執行上述要點的示例腳本

另一種非常簡單的方法是使用LambCI用於模仿Lambda的令人敬畏的docker容器來構建: https//github.com/lambci/docker-lambda

lambci/lambda:build容器類似於AWS Lambda,增加了一個大部分完整的構建環境。 要在其中啟動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容器來測試您的構建。

截至2018年,在AWS EC2上的Python3中安裝外部模塊的步驟:

  1. 在Amazon Linux AMI 201709上啟動EC2。

  2. 使用私鑰和公鑰使用putty進行ssh並成為超級用戶。

  3. 安裝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 
  4. 使用winscp將站點包和dist包下的文件復制到本地machhine中。

    要查找實際位置,請使用grep命令---

      grep -r dist-packages *. 

這些包可以在lib和lib64中。

  1. Site和dist包將在以下位置:

     /tmp/my_python_lib/lib64/python3.6, /tmp/my_python_lib/lib/python3.6 
  2. 將這些包與您的腳本文件一起壓縮並上傳到S3,可以在lambda中訪問。而不是壓縮根文件夾,您必須選擇所有文件並壓縮或發送到壓縮文件夾。

其他提示:

  1. 如果要在一個目錄下安裝所有軟件包,可以使用命令:

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

截至2018年8月,最簡單的方法可能是啟動新的AWS Cloud9環境 然后在環境中創建一個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月 嗨朋友們,這篇文章對我非常有幫助。 但是,到目前為止答案並不是很自動化。 我在這里編寫了一個Python腳本和教程https://gist.github.com/steinwaywhw/6a6a25d594cc07146c60af943f74c16f,以便在EC2上使用pipvirtualenv自動創建編譯的Python包。 一切都是Python(Boto3),沒有bash腳本,沒有Web控制台,沒有awscli

除了自動化之外還有另外一個變化,我認為這是一種改進。 我從EC2下載了整個Python虛擬環境,保留了它的文件夾結構,而不是將liblib64包合並在一起。 我永遠不會理解合並這兩個文件夾的意圖。 如果某些包覆蓋其他包,該怎么辦? 偽裝成官方虛擬環境絕對不是一種更安全的方式,而不是滾動自己的方式。

為了使下載的虛擬環境起作用,Lambda函數的源代碼添加了一些樣板代碼,以使用sys.path更新Python搜索路徑。 可以通過以下方式找到Python虛擬環境的預期sys.path

  • 在您自己的計算機上,創建虛擬環境並將其激活。
  • 在此虛擬環境中運行Python腳本,並在import sys后執行print(sys.path) 您可以從那里開始並根據需要進行修改。

下面粘貼了一個樣板代碼片段,用於為Lambda函數添加以便從我的打包虛擬環境中加載numpy和其他包。 就我而言,我加載了pandas_datareader ,它依賴於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

我可以確認@ 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。

我喜歡@Vito Limandibhrata的答案,但我認為用numpy == 1.11.1中的runtime_library_dirs構建numpy是不夠的。 如果有人認為site-cfg被忽略,請執行以下操作:

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

* .atlas-sse3下的.a文件需要構建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用於使用runtime_library_dirs構建numpy,則最好創建~/.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文件。 這是非常簡單和容易的方式。

您可以在任何操作系統上使用 scipy、numpy、moviepy 和 pandas 為 lambda 創建 zip 文件。

https://pypi.org/project/scipy/#files

pypi 有適用於不同操作系統的 wheel 文件,你可以下載 manylinux whl 文件並解壓。 之后刪除 dist-info 和 pyc 文件以及 zip 全部。 最終的zip文件可以上傳到S3然后轉換成lambda層。

教程有助於深入理解它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM