我正在构建python 3.6
AWS Lambda部署程序包,但遇到了SQLite
的问题。
在我的代码中,我使用的nltk
在其中一个文件中有import sqlite3
。
到目前为止的步骤:
部署包只有我在root用户使用的python模块。我收到错误:
Unable to import module 'my_program': No module named '_sqlite3'
将/home/my_username/anaconda2/envs/py3k/lib/python3.6/lib-dynload/_sqlite3.so
中的_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 lambda env:python3
如何解决此问题?
答案 0 :(得分:32)
根据您对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,那么这种技术可能会有效。
答案 1 :(得分:9)
这有点像黑客攻击,但我已经通过将CentOS 7上的Python 3.6中的_sqlite3.so
文件直接放入使用Zappa部署到AWS的项目的根目录来实现这一点。这应该意味着,如果您可以将_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
祝你好运!答案 2 :(得分:6)
这不是解决方案,但我有解释原因。
Python 3在标准库中支持sqlite(稳定到点知道并且不允许安装pysqlite)。但是,此库要求sqlite开发人员工具(C libs)在运行时位于计算机上。亚马逊的Linux AMI默认没有安装这些,这是AWS Lambda运行的(裸ami实例)。我不确定这是否意味着没有安装sqlite支持,或者只是在添加库之后才会工作,因为我测试的是错误的顺序。
Python 2不支持标准库中的sqlite,你必须使用像pysqlite这样的第三方库来获得支持。这意味着可以更轻松地构建二进制文件,而不依赖于机器状态或路径变量。
我的建议,我已经完成了,如果可以的话,只需在python 2.7中运行该功能(并使你的单元测试更加困难:/)。
由于存在局限性(它是3中融入python的基础库的东西),因此创建一个lambda友好的部署包更加困难。我唯一可以建议的是请求AWS向lambda添加该支持,或者(如果你可以通过nltk实际上使用 sqlite片段而逃脱)通过放置具有适当的空白库来复制anaconda方法和属性但实际上并没有做任何事情。
如果您对后者感到好奇,请查看anaconda安装中的任何fake/_sqlite3
文件。这个想法只是为了避免导入错误。
答案 3 :(得分:2)
正如冷漠人所描述的那样,直到亚马逊将sqlite3
所需的C库捆绑到用于在lambda上运行Python的AMI之前,才有直接的解决方案。
一种解决方法是使用SQLite的纯Python实现,例如PyDbLite。这就解决了这个问题,因为像这样的库并不需要安装任何特定的C库,只需要安装Python。
不幸的是,如果您使用的是库,而后者又使用sqlite3
模块,则无法帮助您。
答案 4 :(得分:1)
我的解决方案可能适用于您,也可能不适用于您(因为它取决于Python 3.5),但希望它可以为类似的问题提供一些启示。
sqlite3
附带标准库,但不是使用AWS使用的python3.6构建的,其原因由apathyman
和其他答案解释。
快速入侵是将共享对象.so
包含在lambda包中:
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
如果您使用的是使用python3.6构建的_sqlite3.so
,则此解决方案可能无效,因为AWS构建的libpython3.6可能不支持此功能。但是,这只是我的教育猜测。如果有人成功完成,请告诉我。
答案 5 :(得分:1)
虽然不是一个很好的方法,但效果很好。使用pickle module
使用本地系统 将您想要的任何功能转储到单独的文件中。将该文件导出到 AWS 项目目录,从文件加载功能并使用它。
所以,这是我尝试过的,当我尝试从 stopwords
导入 nltk.corpus
时遇到了同样的问题,但 AWS 不允许我导入它,即使安装它似乎也没有由于相同的错误 _sqlite3 module not found
,我可以在 Amazon AMI 上使用。为此,我尝试使用本地系统生成一个文件并将停用词转储到其中。这是代码
# Only for Local System
from nltk.corpus import stopwords
import pickle
stop = list(stopwords.words('English'))
with open('stopwords.pkl', 'wb') as f:
pickle.dump(stop, f)
现在,我使用 winscp
将此文件导出到 AWS Directory,然后通过从我项目中的文件加载它来使用该功能。
import pickle
# loading trained model
with open('stopwords.pkl', 'rb') as f:
stop = pickle.load(f)
它工作得很好
答案 6 :(得分:0)
从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)
答案 7 :(得分:0)
您需要sqlite3.so文件(正如其他人所指出的那样),但获取该文件的最可靠方法是从lambci / lambda中可用的(半官方的)AWS Lambda docker映像中拉取。例如,对于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构建/打包,则将其复制到lambda环境包的顶层(即,在其他python文件旁边)。