_python 3.6
_ AWS Lambdaデプロイパッケージを作成していますが、SQLite
の問題に直面していました。
私のコードでは、ファイルの1つに_import sqlite3
_があるnltk
を使用しています。
これまでの手順:
展開パッケージには、ルートで使用しているpythonモジュールのみがあります。エラーが表示されます:_Unable to import module 'my_program': No module named '_sqlite3'
_
_sqlite3.soを_/home/my_username/anaconda2/envs/py3k/lib/python3.6/lib-dynload/_sqlite3.so
_からパッケージルートに追加しました。その後、私のエラーは次のように変わりました:
Unable to import module 'my_program': dynamic module does not define module export function (PyInit__sqlite3)
_sqlite.org
_からSQLiteプリコンパイル済みバイナリをパッケージのルートに追加しましたが、ポイント2でエラーが発生します。
私のセットアップ:_Ubuntu 16.04
_、_python3 virtual env
_
AWSラムダ環境:_python3
_
この問題を修正するにはどうすればよいですか?
NLTKで何をしているかに応じて、解決策を見つけたかもしれません。
ベースnltkモジュールは多くの依存関係をインポートしますが、その多くはその機能セットの大部分では使用されません。私の使用例では、nltk.sent_tokenize
のみを使用しています。これは、sqlite3が依存関係としてインポートされても、sqlite3に機能的な依存関係を持ちません。
変更してAWS Lambdaでコードを機能させることができました
import nltk
に
import imp
import sys
sys.modules["sqlite"] = imp.new_module("sqlite")
sys.modules["sqlite3.dbapi2"] = imp.new_module("sqlite.dbapi2")
import nltk
これにより、sqlite
およびsqlite.dbapi2
の空のモジュールが動的に作成されます。 nltk.corpus.reader.panlex_lite
がsqlite
をインポートしようとすると、標準ライブラリバージョンではなく空のモジュールが取得されます。これはインポートが成功することを意味しますが、nltkがsqliteモジュールを使用しようとすると失敗することも意味します。
実際にsqliteに依存する機能を使用している場合、私は仕方がありません。しかし、他のnltk機能を使用しようとしていて、単にsqliteの不足を回避する必要がある場合、この手法は機能するかもしれません。
これはちょっとしたハックですが、_sqlite3.so
ファイルをPython 3.6からZappaでデプロイされているプロジェクトのルートに直接ドロップすることで機能します。これは、_sqlite3.so
を直接Zipのルートに含めることができれば機能することを意味するので、この行でcpython
にインポートできます。
https://github.com/python/cpython/blob/3.6/Lib/sqlite3/dbapi2.py#L27
きれいではありませんが、動作します。 _sqlite.so
のコピーは次の場所にあります。
https://github.com/Miserlou/lambda-packages/files/1425358/_sqlite3.so.Zip
幸運を!
これは解決策ではありませんが、理由を説明しています。
Python 3は標準ライブラリでsqliteをサポートしています(pipがpysqliteのインストールを許可し、許可しない点まで安定)。ただし、このライブラリを使用するには、実行時にマシン上にsqlite開発者ツール(Cライブラリ)が必要です。 AmazonのLinux AMIにはこれらがデフォルトでインストールされていません。これはAWS Lambdaが実行されるものです(ネイキッドAMIインスタンス)。ただし、これは、間違った順序でテストしたため、sqliteサポートがインストールされていないのか、ライブラリが追加されるまで機能しないのかわかりません。
Python 2は標準ライブラリのsqliteをサポートしていません。そのサポートを得るには、pysqliteのようなサードパーティのライブラリを使用する必要があります。これは、マシンの状態やパス変数に依存せずに、バイナリをより簡単に構築できることを意味します。
あなたがすでに見た私の提案は、可能であればその関数をpython 2.7で実行することです(そしてユニットテストをそれだけ難しくします:/)。
制限(3でpythonのベースライブラリに焼き付けられたもの)のため、ラムダフレンドリーな展開パッケージを作成することはより困難です。私が提案できる唯一のことは、AWSに請願してラムダにそのサポートを追加するか、(実際にsing nltkのsqliteピースを使わずに逃げることができる場合)適切な空のライブラリを入れてanacondaをコピーすることですメソッドと属性ですが、実際には何もしません。
後者に興味がある場合は、fake/_sqlite3
ファイルはanacondaインストールに含まれます。考え方は、インポートエラーを回避することだけです。
Apathymanが説明するように、Amazonがsqlite3
に必要なCライブラリをPython lambdaで実行するために使用されるAMIにバンドルするまで、これに対する直接的な解決策はありません.
回避策の1つは、純粋なPython PyDbLite などのSQLiteの実装を使用することです。このようなライブラリは、このようなライブラリを必要としないため、インストールする特定のCライブラリ、Pythonのみ。
残念ながら、これはsqlite3
モジュールを順番に使用するライブラリを使用している場合には役に立ちません。
私の解決策はあなたに当てはまるかもしれないし当てはまらないかもしれません(Python 3.5)に依存するため).
sqlite3
には標準ライブラリが付属していますが、AWSが使用するpython3.6ではビルドされていません。理由はapathyman
およびその他の回答で説明されています。
簡単なハックは、共有オブジェクト.so
をラムダパッケージに含めることです。
find ~ -name _sqlite3.so
私の場合:
/home/user/anaconda3/pkgs/python-3.5.2-0/lib/python3.5/lib-dynload/_sqlite3.so
ただし、それだけでは十分ではありません。あなたが取得します:
ImportError: libpython3.5m.so.1.0: cannot open shared object file: No such file or directory
_sqlite3.so
はpython3.5で構築されているため、python3.5共有オブジェクトも必要です。パッケージの展開でも必要になります。
find ~ -name libpython3.5m.so*
私の場合:
/home/user/anaconda3/pkgs/python-3.5.2-0/lib/libpython3.5m.so.1.0
AWSによって構築されたlibpython3.6はこれをサポートしない可能性が高いため、python3.6で構築された_sqlite3.so
を使用している場合、このソリューションはおそらく機能しません。ただし、これは単なる教育上の推測です。誰かが成功した場合、私に知らせてください。
Sqlite3.soファイルが必要ですが(他の人が指摘しているように)、それを取得する最も堅牢な方法は、lambci/lambdaで利用可能な(半公式?)AWS Lambdaドッカーイメージからプルすることです。たとえば、Python 3.7の場合、これを行う簡単な方法を次に示します。
最初に、Dockerイメージからsqlite3.so(ライブラリファイル)を取得します。
mkdir lib
docker run -v $PWD:$PWD lambci/lambda:build-python3.7 bash -c "cp sqlite3.cpython*.so $PWD/lib/"
次に、要件とコードを使用して圧縮された実行可能ファイルを作成します。
pip install -t output requirements.txt
pip install . -t output
Zip -r output.Zip output
最後に、ライブラリファイルを画像に追加します。
cd lib && Zip -r ../output.Zip sqlite3.cpython*.so
AWS SAMビルド/パッケージングを使用する場合は、代わりにラムダ環境パッケージの最上位(つまり、他のpythonファイル)の隣)にコピーします。
AusIVの答えから、このバージョンはAWS LambdaとNLTKで動作するため、必要な参照を模擬するためにdummysqlliteファイルを作成しました。
spec = importlib.util.spec_from_file_location("_sqlite3","/dummysqllite.py")
sys.modules["_sqlite3"] = importlib.util.module_from_spec(spec)
sys.modules["sqlite3"] = importlib.util.module_from_spec(spec)
sys.modules["sqlite3.dbapi2"] = importlib.util.module_from_spec(spec)