【问题标题】:How do I get Django connecting to SQL Server working with AWS Lambda Layers?如何让 Django 连接到使用 AWS Lambda 层的 SQL Server?
【发布时间】:2020-07-16 18:17:49
【问题描述】:

我正在尝试在使用 Lambda 层的 AWS Lambda 函数中使用连接到 SQL Server 2019 的 Django。我在这里找到了一个使用 pyodbc 连接到 SQL Server 的示例:https://medium.com/@kuharan/aws-lambda-python-ms-sql-server-the-easy-way-e7667d371cc5
我下载了示例 Lambda 层和 Lambda 函数,并且能够使其正常工作。但是,现在我正在尝试在层中安装 Django 和 django-mssql-backend,以便使用 Django 连接到 SQL Server 2019。这是安装 Django 和 django-mssql-backend 时如何设置目录结构的屏幕截图:

我压缩了pyodbc-layers 文件夹并将其上传到Layers。这是一个截图:

然后当我运行我的 lambda 函数时,我得到了错误:

Response:  
{  
    "errorMessage": "Unable to import module 'lambda_function': No module named 'django'",  
    "errorType": "Runtime.ImportModuleError"  
}

这是我的功能截图和错误信息:

我该如何解决这个问题?谢谢!

编辑:

这是我所有的文本代码:

lambda_function.py:

import json
import os
from datetime import datetime, timedelta

import django

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
django.setup()

from models.models import Schedule


def lambda_handler(event, context):
    games = Schedule.objects.using('default').filter(
        game_date=(
            datetime.today() - timedelta(days=1)
        ).date().strftime('%Y-%m-%d')
    ).values()
    
    print(games)

settings.py:

DEBUG = True

DATABASE_HOSTNAME = 'some_host'
DATABASE_USER = 'some_user'
DATABASE_PASSWORD = 'some_password'
DRIVER = 'ODBC Driver 17 for SQL Server'

SECRET_KEY = 'some_key'

DATE_INPUT_FORMATS = '%Y-%m-%d'

INSTALLED_APPS = (
    'models',
)

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'NAME': 'database_name',
        'ENGINE': 'sql_server.pyodbc',
        'HOST': DATABASE_HOSTNAME,
        'USER': DATABASE_USER,
        'PASSWORD': DATABASE_PASSWORD,
        'OPTIONS': {
            'driver': DRIVER,
            'isolation_level': 'READ UNCOMMITTED'
        },
    }
}

models.models.py:

from django.db import models

class Schedule(models.Model):
    game_id = models.IntegerField(primary_key=True)
    game_date = models.DateField()

    class Meta:
        app_label = 'models'
        managed = True
        db_table = 'Schedule'

按照以下说明使用此代码和 lambda 层构建的完整错误消息:

{
  "errorMessage": "('IM002', '[IM002] [unixODBC][Driver Manager]Data source name not found, and no default driver specified (0) (SQLDriverConnect)')",
  "errorType": "InterfaceError",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 20, in lambda_handler\n    print(games)\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/models/query.py\", line 250, in __repr__\n    data = list(self[:REPR_OUTPUT_SIZE + 1])\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/models/query.py\", line 274, in __iter__\n    self._fetch_all()\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/models/query.py\", line 1242, in _fetch_all\n    self._result_cache = list(self._iterable_class(self))\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/models/query.py\", line 113, in __iter__\n    for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/models/sql/compiler.py\", line 1092, in results_iter\n    results = self.execute_sql(MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size)\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/models/sql/compiler.py\", line 1127, in execute_sql\n    sql, params = self.as_sql()\n",
    "  File \"/opt/python/lib/python3.7/site-packages/sql_server/pyodbc/compiler.py\", line 177, in as_sql\n    supports_offset_clause = self.connection.sql_server_version >= 2012\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/utils/functional.py\", line 80, in __get__\n    res = instance.__dict__[self.name] = self.func(instance)\n",
    "  File \"/opt/python/lib/python3.7/site-packages/sql_server/pyodbc/base.py\", line 400, in sql_server_version\n    with self.temporary_connection() as cursor:\n",
    "  File \"/var/lang/lib/python3.7/contextlib.py\", line 112, in __enter__\n    return next(self.gen)\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/backends/base/base.py\", line 593, in temporary_connection\n    with self.cursor() as cursor:\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/backends/base/base.py\", line 256, in cursor\n    return self._cursor()\n",
    "  File \"/opt/python/lib/python3.7/site-packages/sql_server/pyodbc/base.py\", line 218, in _cursor\n    conn = super()._cursor()\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/backends/base/base.py\", line 233, in _cursor\n    self.ensure_connection()\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/backends/base/base.py\", line 217, in ensure_connection\n    self.connect()\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/utils.py\", line 89, in __exit__\n    raise dj_exc_value.with_traceback(traceback) from exc_value\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/backends/base/base.py\", line 217, in ensure_connection\n    self.connect()\n",
    "  File \"/opt/python/lib/python3.7/site-packages/django/db/backends/base/base.py\", line 195, in connect\n    self.connection = self.get_new_connection(conn_params)\n",
    "  File \"/opt/python/lib/python3.7/site-packages/sql_server/pyodbc/base.py\", line 314, in get_new_connection\n    timeout=timeout)\n"
  ]
}

【问题讨论】:

  • 除了截图之外,能否请您提供 lambda 的代码作为文本?

标签: python sql-server django amazon-web-services aws-lambda


【解决方案1】:

我使用docker toolpython 3.8 创建了自定义层。该指令适用于 linux,因为我没有要测试的窗口。不过,这些步骤可以适应 windows。

主要困难在于共享库libltdllibodbc)是odbc 所必需的,但在 lambda 环境中通常不可用。

创建图层

该层将具有django==2.2.12django-mssql-backendpyodbc

# create layer folder on your host operating system
mkdir /tmp/layer1

# run dcoker container for lambda python 3.8
docker run --rm -v /tmp/layer1:/tmp/layer1 -ti lambci/lambda:build-python3.8 /bin/bash

# in the container exectue the following commands

cd /tmp/layer1
yum install -y unixODBC-devel
python -m venv python
source ./python/bin/activate
pip install django==2.2.12 django-mssql-backend pyodbc
zip -r django-odbc.zip .
cp -rvf /usr/lib64/libltdl.so* .
cp -rvf /usr/lib64/libodbc.so* .

使用 django-odbc.zip 创建一个层并记住将 python3.8 设置为兼容的运行时。

使用您的函数创建 lambda 部署包

在你的主机上执行

mkdir /tmp/lambda_function
cd /tmp/lambda_function
cp -rvf /tmp/layer1/*.so* .

同时添加以下文件lambda_function.py:

import json

import django
import pyodbc 

def lambda_handler(event, context):
    # TODO implement 
    
    print(django.get_version())
    
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

制作部署包:

zip -r lambda_function.zip .

使用lambda_function.zip创建lambda函数并添加层django-odbc.zip它。

【讨论】:

  • 我在我的问题中添加了代码。我能够按照您的指示让您的测试层和测试功能正常工作。但是,当我尝试将您的层与我的函数一起使用时,我收到此错误:"('IM002', '[IM002] [unixODBC][Driver Manager]Data source name not found, and no default driver specified (0) (SQLDriverConnect)')"。我将在我的帖子中添加完整的错误消息。
  • 我想我必须在图层的某处添加odbc,iniodbcinst.ini 文件。那应该在哪里?感谢大家的帮助!
  • 我想通了!我必须将您的说明与我从此处下载的 lambda 层合并:github.com/kuharan/Lambda-Layers。除了/tmp/layer1/python/lib64/python3.7/site-packages 中Docker 容器中的pyodbc 包文件之外,我必须将python 包复制到该github 层中的python 文件夹中。然后我把所有东西都拉上拉链,在 AWS 中做了一层。然后在我的 lambda 函数 zip 中,我必须删除所有 lib 文件。
  • @DiZou 很高兴听到它成功了。感谢您让我知道 pyodpc :-)
  • 我认为我必须在我链接的那个 github 中使用 pyodbc 的原因是因为那里的 unixODBC 库被编译指向 /opt (安装层的位置)以查找 @987654351 @ 和 odbcinst.ini。因此,我认为如果在查找/opt 中的.ini 文件时将您的指令更改为编译unixODBC,它将起作用。还有一个选项可以设置一些环境变量:stackoverflow.com/questions/11393269/…
猜你喜欢
  • 2021-05-23
  • 2018-05-20
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
  • 2019-10-07
  • 2017-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多