上AWS拉姆达与Python 3 sqlite3的错误

问题描述 投票:21回答:7

我建立一个python 3.6 AWS LAMBDA部署包和面临的问题与SQLite

在我的代码我使用nltk其在文件中的一个import sqlite3

考虑到现在的步骤:

  1. 部署包都有,我使用的唯一的根Python模块。我得到的错误:Unable to import module 'my_program': No module named '_sqlite3'
  2. 加入从/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)
  3. 新增由sqlite.org SQLite的预编译的二进制我的包的根,但我仍然得到错误的点#2。

我的设置:Ubuntu 16.04python3 virtual env

AWS拉姆达ENV:python3

我怎样才能解决这个问题呢?

python-3.x amazon-web-services sqlite aws-lambda
7个回答
36
投票

这取决于你用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

这种动态创建sqlitesqlite.dbapi2空模块。当nltk.corpus.reader.panlex_lite尝试导入sqlite,这将让我们的空模块,而不是标准库版本。这意味着进口会成功,但它也意味着当NLTK尝试使用SQLite模块就会失败。

如果您使用的是实际上取决于sqlite的任何功能,我怕我忍不住。但是,如果你想使用其他NLTK功能,并且只需要得到周围缺乏源码的,这种技术可能会奏效。


9
投票

这是一个黑客位的,但我已经通过丢弃在Python 3.6在CentOS 7 _sqlite3.so文件直接导入的部署扎帕到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

祝好运!


6
投票

这不是一个解决方案,但我有一个解释这是为什么。

Python 3只有在标准库的SQLite支持(稳定PIP知道的一点,而不是让安装pysqlite的)。然而,这个库需要源码开发工具(C库)是机器在运行时。亚马逊公司的Linux AMI没有在默认情况下,这是AWS LAMBDA上(裸AMI实例)中运行这些安装。我不知道这是否意味着sqlite的支持,未安装或只是将无法工作,直到库添加,但是,因为我在错误的测试顺序的东西。

Python 2中不支持源码在标准库中,你必须使用第三方的lib像pysqlite得到的支持。这意味着二进制文件可以更容易地在不依赖于机器状态或路径变量来构建。

我的建议,你已经完成了我看到的,是刚刚运行的功能在Python 2.7,如果你可以(而且使您的单元测试只是更难:/)。

因为限制(这是什么烤成Python的基础库中3)更难以形成拉姆达友好部署包。我可以建议的唯一的事情是要么上访AWS到支持添加到拉姆达或者(如果你能逃脱,而无需实际使用NLTK sqlite的件)通过将有适当的方法和属性,但不空库复制蟒蛇其实做任何事情。

如果你好奇后,检查出任何fake/_sqlite3文件的蟒蛇安装。我们的想法是,才避免导入错误。


2
投票

作为apathyman介绍,还没有一个直接的解决方案,这一点,直到亚马逊捆绑需要sqlite3到用于在λ运行Python的AMI的C库。

一种解决方法虽然是使用SQLite的纯Python实现,如PyDbLite。这侧步的问题,因为像这样的库,不需要安装任何特定的C库,只是Python的。

不幸的是,如果你使用这反过来使用sqlite3模块库这并不能帮助你。


1
投票

我的解决方案可能会或可能对您不适用(因为它依赖于Python的3.5),但希望它可能会提供一些线索了类似的问题。

sqlite3标配库,但不与python3.6是AWS使用,与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

该解决方案可能是,如果你使用的是内置有python3.6 _sqlite3.so,因为AWS建成libpython3.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)

0
投票

您需要sqlite3.so文件(如其他人指出的),但最可靠的方法来得到它是从拉(半官方的?)在lambci /λ可用AWS LAMBDA泊坞窗图像。例如,对于Python的3.7,这里有一个简单的方法来做到这一点:

首先,让我们抓住从泊坞窗图像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文件)。

© www.soinside.com 2019 - 2024. All rights reserved.