web-dev-qa-db-ja.com

Amazon lambdaでmoviepy、scipy、numpyを使用する

AWS Lambda機能を使用してビデオを生成したいと思います。

here および here の指示に従っています。

そして今、私のLambda関数を構築する次のプロセスがあります:

ステップ1

Amazon Linux EC2インスタンスを起動し、これをルートとして実行します:

#! /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をラップトップにコピーします。次に、このスクリプトを実行して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のアドバイスに従って、lambdafunctionを次のように減らしました。

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
63
rouk1

このスレッドのすべての投稿の助けを借りて、ここに記録の解決策があります:

これを機能させるには、次のことが必要です。

  1. 少なくとも2GO RAMでEC2インスタンスを開始します(NumPyおよびSciPyをコンパイルできるようにするため)

  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. 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
  4. 必要なすべての共有ライブラリをEC2instanceから取得します。

    • 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. それらをlibフォルダーのstackサブフォルダーに入れます

  6. imageiomoviepyの依存関係です。その依存関係のバイナリバージョンをダウンロードする必要があります:libfreeimageおよびffmpeg;それらは こちら で見つけることができます。スタックフォルダーのルートに配置し、libfreeimage-3.16.0-linux64.soからlibfreeimage.soに名前を変更します。

  7. これで、次を含むstackフォルダーができました。

    • ルートのすべてのpython依存関係
    • libサブフォルダー内のすべての共有ライブラリ
    • ffmpegルートのバイナリ
    • libfreeimage.soルートで
  8. このフォルダーを圧縮:Zip -r9 stack.Zip . -x ".*" -x "*/.*"

  9. 次のlambda_function.pylambdaのエントリポイントとして使用します

    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. moviepynumpy、...に依存するmovie_maker.pyscriptを記述する.

  11. スクリプトにそれらをstack.ZipファイルZip -r9 lambda.Zip *.pyに追加します

  12. zipをS3にアップロードし、lambdaのソースとして使用します

stack.Ziphere をダウンロードすることもできます。

27
rouk1

私もあなたの最初のリンクをたどっていて、numpypandasをインポートすることができましたこのようにLambda関数で(Windowsの場合):

  1. 64ビットAmazon Linux AMI 2015.09.1で(無料ティア)t2.microEC2インスタンス を開始し、PuTTYを使用したSSHで.
  2. 使用したものと同じコマンドと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. 仮想環境を作成しました:

    virtualenv ~/env
    source ~/env/bin/activate
    
  4. packagesをインストールしました:

    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 *)をダウンロードしました。 、およびEC2インスタンスの/home/ec2-user/env/lib64/python2.7/site-packagesからのすべて。

  6. Lambda関数を含む.pyファイルとともに、これらすべてのフォルダーとファイルを1つZipに入れます。 コピーされたすべてのファイルの図

  7. この.Zipは10 MBより大きいため、ファイルを保存するためにS3バケットを作成しました。そこからファイルのリンクをコピーし、Lambda関数で「Amazon S3から.Zipをアップロード」で貼り付けました。

  8. EC2インスタンスはshut downである可能性がありますが、もう必要ありません。

これで、numpyとpandasをインポートできました。私はmoviepyに慣れていませんが、Lambdaには262 144 000バイトの展開されていない展開パッケージサイズのlimitがあるため、scipyはすでに扱いにくいかもしれません。私はnumpyとscipyが一緒にすでにそれを超えているのではないかと心配しています。

56
Attila Tanyi

ここの投稿は、AWS Lambda Deploymentパッケージに含めることができるライブラリファイルを使用して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でコードが存在するルートディレクトリです。したがって、この場合は/ 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)
7

2017年現在、NumPyとSciPyにはLambdaで動作するホイールがあります(パッケージにはプリコンパイルされたlibgfortranlibopenblasが含まれます)。私の知る限り、MoviePyは純粋なPythonモジュールなので、基本的には次のようにできます。

pip2 install -t lambda moviepy scipy

次に、ハンドラーをlambdaディレクトリにコピーしてZipします。ただし、50/250 MBのサイズ制限を超える可能性が高いことを除きます。役立つものがいくつかあります。

  • .pycs、ドキュメント、テスト、その他の不要な部分を削除します。
  • numPyとSciPyの共通ライブラリの単一のコピーを残します。
  • デバッグシンボルなど、不要な部分のライブラリを削除します。
  • より高い設定を使用してアーカイブを圧縮します。

上記のポイントを自動化する例 script を次に示します。

6
wrwrwr

最近可能になるもう1つの非常に簡単な方法は、LambCIがLambdaを模倣するために作成した素晴らしいdockerコンテナーを使用してビルドすることです: https://github.com/lambci/docker-lambda

lambci/lambda:buildコンテナは、AWS Lambdaに似ており、ほぼ完全なビルド環境が追加されています。シェルセッションを開始するには:

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コンテナーを使用してビルドをテストできます。

5
johncip

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パッケージの下のファイルをローカルコンピューターにコピーします。

    実際の場所を見つけるには、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にアップロードします。ルートフォルダーを圧縮する代わりに、すべてのファイルを選択して圧縮するか、圧縮フォルダーに送信する必要があります。

追加のヒント:

  1. すべてのパッケージを1つのディレクトリにインストールする場合は、次のコマンドを使用できます。

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

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関数でモジュールをインポートできます。

2
karoli

2018年11月こんにちは友人、この投稿は私にとって非常に役立ちます。ただし、これまでの回答はあまり自動化されていません。ここでPythonスクリプトとチュートリアルを書いた https://Gist.github.com/steinwaywhw/6a6a25d594cc07146c60af943f74c16f を使用して、コンパイルされたPythonパッケージの作成を自動化EC2のpipおよびvirtualenvすべてがPython(Boto3)、bashスクリプト、Webコンソール、awscliでありません。

自動化のほかに1つの変更がありますが、それは改善だと思います。 libパッケージとlib64パッケージをすべてマージする代わりに、フォルダー構造を維持したまま、Python仮想環境全体をEC2からダウンロードしました。これらの2つのフォルダーをマージすることの意図する意味がわかりません。一部のパッケージが他のパッケージをオーバーライドする場合はどうでしょうか?さらに、公式の仮想環境を偽造することは、独自の環境を展開するよりも安全な方法です。

ダウンロードした仮想環境が機能するように、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
2
Steinway Wu

@ attila-tanyiによって投稿されたステップがAmazon Linuxで正しく機能することを確認できます。デフォルトのリポジトリからAmazon Linuxのdockerコンテナが利用可能であるため、EC2を使用する必要がないことだけを追加します。

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

アプリケーションに埋め込まれたDockerfileを使用して、Lambdaにビルドしてデプロイします。

1
Jay Carroll

@Vito Limandibhrataの答えは好きですが、numpy == 1.11.1のruntime_library_dirsでnumpyを構築するだけでは不十分だと思います。誰かがsite-cfgが無視されると思う場合は、次のことを行ってください。

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

* numpyをビルドするには、atlas-sse3の下の.aファイルが必要です。また、次を実行する必要がある場合があります。

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ファイルを認識します。それは非常にシンプルで簡単な方法です。

0
sangheestyle