Ошибка sqlite3 на AWS лямбда с Python 3

Я создаю пакет развертывания python 3.6 AWS Lambda и столкнулся с проблемой SQLite.

В моем коде я использую nltk, у которого есть import sqlite3 в одном из файлов.

Шаги, предпринятые до сих пор:

  • В пакете развертывания есть только модули 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 из sqlite.org в корень моего пакета, но я все еще получаю ошибку как точку № 2.

Моя настройка: Ubuntu 16.04, python3 virtual env

AWS lambda env: python3

Как я могу исправить эту проблему?

Ответ 1

В зависимости от того, что вы делаете с NLTK, я, возможно, нашел решение.

В базовом модуле nltk импортируется множество зависимостей, многие из которых не используются значительными частями его набора функций. В моем случае использования я использую только nltk.sent_tokenize, который не имеет функциональной зависимости от sqlite3, хотя sqlite3 импортируется как зависимость.

Мне удалось заставить мой код работать с AWS Lambda, изменив

import nltk

to

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, этот метод может работать.

Ответ 2

Это не решение, но у меня есть объяснение, почему.

Python 3 поддерживает sqlite в стандартной библиотеке (стабильной до точки звания пика и не допускающей установки pysqlite). Однако эта библиотека требует, чтобы инструменты разработчика sqlite (C libs) находились на машине во время выполнения. У Amazon linux AMI эти установки не установлены по умолчанию, что и работает AWS Lambda (голые экземпляры ami). Я не уверен, означает ли это, что поддержка sqlite не установлена ​​или просто не будет работать до тех пор, пока библиотеки не будут добавлены, потому что я тестировал вещи в неправильном порядке.

Python 2 не поддерживает sqlite в стандартной библиотеке, вам нужно использовать стороннюю lib, например pysqlite, для получения этой поддержки. Это означает, что двоичные файлы могут быть построены более легко, не завися от состояния машины или переменных пути.

Мое предложение, которое вы уже сделали, я вижу, заключается в том, чтобы просто запустить эту функцию в python 2.7, если вы можете (и сделать тестирование вашего устройства намного сложнее:/).

Из-за ограничений (это что-то запекается в базовые библиотеки python в 3), сложнее создать дружественный для lambda пакет развертывания. Единственное, что я могу предложить, - либо просить AWS добавить эту поддержку лямбда, либо (если вы можете уйти без фактического использования кусков sqlite в nltk), скопируйте anaconda, поместив пустые библиотеки, которые имеют надлежащие методы и атрибуты, но не на самом деле что-то делать.

Если вам интересно узнать о последнем, просмотрите любой из файлов fake/_sqlite3 в установке anaconda. Идея заключается только в том, чтобы избежать ошибок импорта.

Ответ 3

Это что-то вроде хака, но я получил эту работу, _sqlite3.so файл _sqlite3.so из Python 3.6 на CentOS 7 непосредственно в корень проекта, развертываемого с 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

Удачи!

Ответ 4

Как описывает апатиман, нет прямого решения, пока Amazon не свяжет библиотеки C, необходимые для sqlite3, в AMI, используемый для запуска Python на лямбда.

Одно из решений, использующих чистую реализацию SQLite для Python, например PyDbLite. Эта проблема устраняет проблему, так как библиотека, подобная этой, не требует установки каких-либо конкретных библиотек C, а просто Python.

К сожалению, это не поможет вам, если вы используете библиотеку, которая, в свою очередь, использует модуль sqlite3.

Ответ 5

Мое решение может относиться или не относиться к вам (так как оно зависит от 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

Это решение, скорее всего, не будет работать, если вы используете _sqlite3.so, созданный с помощью python3.6, потому что libpython3.6, созданный AWS, скорее всего, не будет поддерживать это. Тем не менее, это всего лишь мое образовательное предположение. Если кто-то успешно сделал, пожалуйста, дайте мне знать.

Ответ 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, доступных в lambci/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/"

Далее мы создадим zip файл с нашими требованиями и кодом:

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).