【问题标题】:sqlite3 error on AWS lambda with Python 3使用 Python 3 的 AWS lambda 上的 sqlite3 错误
【发布时间】:2017-10-18 21:17:07
【问题描述】:

我正在构建一个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 lambda 环境:python3

我该如何解决这个问题?

【问题讨论】:

  • 它适用于 AWS Lambda 环境中的 python 2.7。可能是 python3 环境没有支持 sqlite3 的二进制文件。但我的问题仍然存在。如何将二进制文件打包到 aws lambda 中以在我的 python 包中利用它们。
  • 我什至尝试将libsqlite3.so 复制到压缩包的lib 目录中,但这并没有帮助。有人解决这个问题吗?
  • 在 AWS 将其添加到 AMI 之前,您很不走运。人们在下面提出了一些不错的解决方案
  • 感谢@Darthsidious,但不确定为什么无法将库显式添加到 zip 中。我想我还在学习这些限制。
  • 我已经尝试了 sqlite.so 的 zip 中的每个位置

标签: python-3.x amazon-web-services sqlite aws-lambda


【解决方案1】:

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

Python 3 在标准库中支持 sqlite(稳定到知道 pip 并且不允许安装 pysqlite)。然而,这个库需要 sqlite 开发者工具(C 库)在运行时在机器上。 Amazon 的 linux AMI 默认没有安装这些,这是 AWS Lambda 运行的(裸 ami 实例)。不过,我不确定这是否意味着没有安装 sqlite 支持,或者在添加库之前无法工作,因为我以错误的顺序进行了测试。

Python 2 在标准库中不支持 sqlite,您必须使用第三方库(如 pysqlite)来获得支持。这意味着可以更轻松地构建二进制文件,而无需依赖机器状态或路径变量。

我的建议是,如果可以的话,您已经在 python 2.7 中运行该函数(并使您的单元测试变得更加困难:/)。

由于限制(它在 3 中被嵌入到 python 的基本库中),创建一个对 lambda 友好的部署包更加困难。我唯一能建议的就是请求 AWS 将这种支持添加到 lambda 或者(如果你可以在没有实际使用 nltk 中的 sqlite 片段的情况下逃脱)通过放置具有适当的空白库来复制 anaconda方法和属性,但实际上并没有做任何事情。

如果您对后者感到好奇,请查看 anaconda 安装中的任何 fake/_sqlite3 文件。这个想法只是为了避免导入错误。

【讨论】:

    【解决方案2】:

    正如 apathyman 所描述的,在 Amazon 将 sqlite3 所需的 C 库捆绑到用于在 lambda 上运行 Python 的 AMI 中之前,没有直接的解决方案。

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

    不幸的是,如果您使用的库又使用 sqlite3 模块,这对您没有帮助。

    【讨论】:

    • PyDbLite 不是 sqlite 的实现
    【解决方案3】:

    根据您使用 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 功能并且只需要解决缺少 sqlite 的问题,那么这种技术可能会起作用。

    【讨论】:

    • 这可行,但之后我被要求安装python -m textblob.download_corpora。我应该把这个文件放在哪里?
    【解决方案4】:

    这有点小题大做,但我通过将 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

    祝你好运!

    【讨论】:

    • 绝对有效..感谢预建的“.so”文件!
    • 完美。谢谢!
    • 我有一个不同的情况,当我把_sqlite3.so文件放到文件夹里时,sqliteCache需要sqlite3模块的错误不见了,但是又出现了一个错误:[Errno 30] Read-只有文件系统:'/home/sbx_user1051' 有什么建议吗?
    【解决方案5】:

    我的解决方案可能适用于您,也可能不适用于您(因为它取决于 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 可能不支持此功能。然而,这只是我的教育猜测。如果有人成功了,请告诉我。

    【讨论】:

      【解决方案6】:

      根据 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】:

        您需要 sqlite3.so 文件(正如其他人所指出的那样),但获得它的最可靠方法是从(半官方?)AWS Lambda docker 镜像中提取,该镜像在 lambci/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 构建/打包,请将其复制到 lambda 环境包的顶层(即,在您的其他 python 文件旁边)。

        【讨论】:

          【解决方案8】:

          TL;DR

          虽然不是一个很好的方法,但它工作得很好。使用pickle module 将您想要的任何功能转储到一个使用本地系统 的单独文件中。将该文件导出到 AWS 项目目录,从文件中加载功能并使用它。

          长期

          所以,这就是我尝试的方法,当我尝试从 nltk.corpus 导入 stopwords 时遇到了同样的问题,但 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)
          

          而且效果很好

          【讨论】:

            猜你喜欢
            • 2017-03-10
            • 2018-08-19
            • 1970-01-01
            • 2018-08-21
            • 2021-05-04
            • 2018-04-12
            • 2016-07-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多