Невозможно использовать pyodbc с AWS лямбда и API-шлюзом

Я пытаюсь создать функцию AWS Lambda, используя APi Gateway, который использует пакет pyodbc python. Я следовал за шагами как упомянуто в документации. Я получаю следующее сообщение об ошибке: " Невозможно импортировать модуль" приложение ": libodbc.so.2: невозможно открыть общий объектный файл: нет такого файла или каталога, когда я тестирую, запускаю функцию Lambda.

Любая помощь приветствуется. Я получаю ту же ошибку при развертывании пакета с помощью Chalice. Кажется, может быть, мне нужно установить unixodbc-dev. Есть идеи, как это сделать через AWS Lambda?

6 ответов

Просто распакуйте этот файл отсюда - github - lambda_packages / pyodbc. В нем есть файлы.so.

Теперь упакуйте код Python и файлы.so вместе и загрузите в AWS lambda. Структура папок для справки должна выглядеть следующим образом.

lambda_function.py
libodbc.so.2
pyodbc.so
<name_this_zip>.zip

No subfolders exist

pyodbc использует некоторые родные библиотеки. Поэтому вы не можете просто скопировать содержимое вашего site-packages к лямбде, так как ваша ОС скорее всего не Amazon Linux.

Поэтому вам нужно установить pyodbc на экземпляр Amazon Linux и использовать сгенерированные библиотеки:

https://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html

Или вы можете получить отсюда, если доступно там:

https://github.com/Miserlou/lambda-packages

Fisrt, установить unixODBC а также unixODBC-devel пакеты, использующие yum install unixODBC unixODBC-devel, Этот шаг установит все необходимое для модуля pyodbc.

Библиотека, которую вы пропустили, находится в /usr/lib64 Папка на вашем экземпляре Amazon Linux. Скопируйте библиотеку в корневую папку вашего проекта Python (libodbc.so.2 - просто символическая ссылка, убедитесь, что вы скопировали символическую ссылку и саму библиотеку, как указано): libodbc.so, libodbc.so.2 а также libodbc.so.2.0.0

Я решил это, добавив пакет pyodbc git в качестве лямбда-слоя и установив версию python на образец кода 3.7.

      conn = pyodbc.connect("DRIVER={0};SERVER={1};DATABASE={2};UID={3};PWD={4}".format(driver, server, database, username, password))

вы можете скачать слой pyodbc из GIThttps://github.com/karthigces/lambda_layers

Попробуйте запустить этот скрипт, чтобы собрать зависимость в корзину s3, а затем добавить ее в ваш пакет развертывания лямбда-выражений.

""" 
This lambda function collects python pip dependencies, and uploads them to S3 bucket 
as a single tar.gz file. Example input for Lambda event: 
    event = {
        "prefix"            : "myPackage",
        "saveToS3Bucket"    : "my-s3-bucket",
        "saveToS3Key"       : "package-jwt.tar.gz",
        "requirements"      : [ "cryptography==2.1.3",
                                "PyJWT==1.5.3" ]
    }

Minimal Lambda execution role:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "Stmt1507151548000",
                "Effect": "Allow",
                "Action": [
                    "s3:PutObject"
                ],
                "Resource": [
                    "arn:aws:s3:::my-s3-bucket/package-jwt.tar.gz"
                ]
            },
            {
                "Effect": "Allow",
                "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                ],
                "Resource": "*"
            }
        ]
    }
"""

from subprocess import check_output
import uuid
import boto3

DEBUG_OUT_FILE = "/tmp/debug.txt"
S3 = boto3.resource('s3')


def lambda_handler(event, context):
    """ 
    """

    requirements = event.get('requirements', [])
    prefix = event.get('prefix', 'myPackage')
    saveToS3Bucket = event.get('saveToS3Bucket', None)
    saveToS3Key = event.get('saveToS3Key', None)
    location = "%s_%s" % (prefix, uuid.uuid4())
    destinationPath = '/tmp/%s' % location
    tarFileName = '/tmp/%s.tar.gz' % location

    for req in requirements:
        _exec(['pip', 'install', req, '-t', destinationPath])

    _exec(['tar', 'czvf', tarFileName, destinationPath])
    _persist_file_to_s3(tarFileName, saveToS3Bucket, saveToS3Key)
    return 'done!'


def _exec(statements):
    if statements and type(statements) == list:
        with open(DEBUG_OUT_FILE, "a") as f:
            try:
                f.write("\n$ %s \n" % " ".join(statements))
                rv = check_output(statements).decode("utf8")
                f.write(rv)
                print(rv)
            except Exception as ex:
                print(ex)
                f.write(str(ex))


def _persist_file_to_s3(filePathToUpload, s3Bucket, s3Key):
    if filePathToUpload and s3Bucket and s3Key:
        S3.meta.client.upload_file(filePathToUpload, s3Bucket, s3Key)

@joarleymoraes ответ правильный.

Каждый экземпляр Lambda под капотом представляет собой контейнер, созданный из AMI Amazon Linux. pyodbc нуждается в некоторых собственных библиотеках для работы, которые по умолчанию отсутствуют внутри контейнера Lambda. Итак, чтобы все работало, вам необходимо убедиться, что среда Lambda включает эти собственные библиотеки в дополнение к pyodbc и вашему коду функции.

См. https://medium.com/@narayan.anurag/breaking-the-ice-between-aws-lambda-pyodbc-6f53d5e2bd26, чтобы узнать больше о проблеме и ее решении.

Другие вопросы по тегам