将 psycopg2 与 Lambda 结合使用以更新 Redshift (Python)

Using psycopg2 with Lambda to Update Redshift (Python)

提问人:awsQuestion 提问时间:4/14/2016 最后编辑:hjpotter92awsQuestion 更新时间:11/17/2023 访问量:56040

问:

我正在尝试使用 python 从 Lambda 函数更新 Redshift。为此,我正在尝试组合 2 个代码片段。当我单独运行它们时,这两个片段都可以正常工作。

  1. 从 PyDev for Eclipse 更新 Redshift

    import psycopg2
    
    conn_string = "dbname='name' port='0000' user='name' password='pwd' host='url'"
    conn = psycopg2.connect(conn_string)
    
    cursor = conn.cursor()
    
    cursor.execute("UPDATE table SET attribute='new'")
    conn.commit()
    cursor.close()
    
  2. 接收上传到 S3 存储桶的内容(Lambda 上提供的预构建模板)

    from __future__ import print_function
    
    import json
    import urllib
    import boto3
    
    print('Loading function')
    
    s3 = boto3.client('s3')
    
    
    def lambda_handler(event, context):
        #print("Received event: " + json.dumps(event, indent=2))
    
        # Get the object from the event and show its content type
        bucket = event['Records'][0]['s3']['bucket']['name']
        key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key']).decode('utf8')
    
        try:
            response = s3.get_object(Bucket=bucket, Key=key)
            print("CONTENT TYPE: " + response['ContentType'])
            return response['ContentType']
    
        except Exception as e:
            print(e)
            print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
            raise e
    

由于这两个部分都有效,我尝试将它们组合在一起,以便在将文件上传到 s3 时更新 Redshift:

from __future__ import print_function

import json
import urllib
import boto3
import psycopg2

print('Loading function')

s3 = boto3.client('s3')


def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))

    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key']).decode('utf8')

    conn_string = "dbname='name' port='0000' user='name' password='pwd' host='url'"

    conn = psycopg2.connect(conn_string)

    cursor = conn.cursor()

    cursor.execute("UPDATE table SET attribute='new'")
    conn.commit()
    cursor.close()

    try:
        response = s3.get_object(Bucket=bucket, Key=key)
        print("CONTENT TYPE: " + response['Body'].read())
        return response['Body'].read()
    except Exception as e:
        print(e)
        print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
        raise e

由于我使用的是外部库,因此需要创建一个部署包。我创建了一个新文件夹 (lambda_function1) 并将我的.py文件 (lambda_function1.py) 移动到该文件夹。我运行以下命令在该文件夹中安装 psycopg2:

pip install psycopg2 -t \lambda_function1

我收到以下反馈:

Collecting psycopg2
  Using cached psycopg2-2.6.1-cp34-none-win_amd64.whl
Installing collected packages: psycopg2
Successfully installed psycopg2-2.6.1 

然后,我压缩了目录的内容。并将该 zip 上传到我的 lambda 函数。当我将文档上传到函数监控的存储桶时,我在 cloudwatch 日志中收到以下错误:

Unable to import module 'lambda_function1': No module named _psycopg 

当我查看库时,唯一名为“_psycopg”的是“_psycopg.pyd”。

是什么导致了这个问题?当我使用 Python 3.4 时,Lambda 使用 Python 2.7 有关系吗?我在 Windows 机器上压缩文件内容有关系吗?有没有人能够从 lambda 成功连接到 Redshift?

python 亚马逊网络服务 aws-lambda 亚马逊 redshift aws-sdk

评论

2赞 bbayles 4/14/2016
遗憾的是,您将无法在 Lambda 上使用 Windows 创建的 wheel 文件。您可以在 Lambda 上使用 pg8000(纯 Python)和 Redshift。

答:

32赞 Vor 4/14/2016 #1

为此,您需要使用静态链接库进行构建。查看此 repo https://github.com/jkehler/awslambda-psycopg2。它已经构建了 psycopg2 包,并说明了如何自己构建它。psycopg2libpq.so

回到您的问题:

是什么导致了这个问题?

psycopg2需要使用适用于 Linux 的静态链接库进行构建和编译。

当我使用 Python 3.4 时,Lambda 使用 Python 2.7 有关系吗?

是的,lambda 仅支持 2.7 版本。只需创建虚拟环境并在其中安装所有必要的软件包即可。

我在 Windows 机器上压缩文件内容有关系吗?

只要您压缩的所有库都可以在 Linux 上运行,它就不能

有没有人能够从 lambda 成功连接到 Redshift?

是的。

评论

0赞 awsQuestion 4/15/2016
非常感谢!我从 git hub 下载并提取了 zip 并将其粘贴到我的部署包中,它立即起作用(无需更改 Python 版本)。非常感谢您的帮助!
0赞 Sarang Manjrekar 4/5/2017
当我尝试更新时,类似于问题的第 1 部分:、、、、import psycopg2conn_string = "dbname='............ etcconn = psycopg2.connect(conn_string)cursor = conn.cursor()cursor.execute("Update Query")DatabaseError: SSL SYSCALL error: Operation timed out
0赞 ifti 5/14/2017
@Vor我从 git 复制了 psycopg2 文件夹并粘贴了 lambda zip 仍然出现以下错误。无法导入模块“core_handler”:没有名为 psycopg2._psycopg 的模块
1赞 Davos 11/20/2018
更新:Lambda 现在支持 python 2.7 或 python 3.6
1赞 XPX-Gloom 3/9/2019
我在答案中分叉了 repo,用 Python 3.7 + PostgreSQL 10.7 编译,这里是:github.com/pzmosquito/awslambda-psycopg2
17赞 jshammon 4/28/2019 #2

我刚刚遇到了同样的问题。我偶然发现了另一个答案中提到的同一个 github 项目,它解释了这个问题如下:

由于 AWS Lambda 在 AMI 映像中缺少所需的 PostgreSQL 库,因此我们需要使用 PostgreSQL libpq.so 库静态链接的 libpq 库而不是默认的动态链接来编译 psycopg2。

这在之前的回答中已经注意到了,我开始按照说明为自己构建一个带有静态链接 PostgreSQL 库的 psycopg2 版本。不过,我发现了一个更简单的选择。我在 psycopg2 github 页面上注意到以下内容:

您还可以通过从 PyPI 安装 psycopg2-binary 包来获取不需要编译器或外部库的独立包:

$ pip install psycopg2-binary

二进制包是开发和测试的实用选择,但在生产中,建议使用从源代码构建的包。

当我pip安装了psycopg2二进制包并将其包含在我的requirements.txt文件中时,我能够完美地从lambda函数连接到我的postgresql数据库。我正在使用我强烈推荐的圣杯。我意识到 psycopg2 建议不要将二进制版本用于生产,但我看不出使用二进制版本或自己编译和静态链接之间没有太大区别。如果我错了,有人请纠正我。

评论

0赞 Iago Leão 7/19/2019
这是为我找到的
2赞 paulkernfeld 11/30/2021
我很好奇你用的是什么操作系统。我的猜测是,这只有在您运行的平台与 AWS Lambda 二进制兼容时才有效。pip install psycopg2-binary
1赞 David Stannard 7/8/2019 #3

假设您的打包正确,该错误通常表示 psycopg2 部署的二进制文件对于您的目标操作系统或 Python 版本不正确。no module named psycopg2

对于 Lambdas,我们发现 psycopg2 二进制文件有效(使用 manylinux_x86_64)。据报道,由于存在相互竞争的 libssl 二进制文件,存在段错误的风险,尽管我们还没有。 (这基本上是 jshammon 上面答案的 +1)

“正确的解决方案”可能是专门针对 Lambda 的 jkehlers 重新编译,仅缺少 ,但它目前不支持 ssl+py3.7,而且我们太 Windows 了,无法自己重新编译它。lib_pq.so

12赞 Sumit Chhabra 8/1/2019 #4

要将 psycopg2 与 aws lambda 结合使用,请使用 import aws-psycopg2

由于 aws 支持 psycopg2,但导入 psycopg2 的方式略有不同,因为 aws 本身有一个编译的 psycopg2 库,因此我们需要使用 aws-psycopg2 进行导入

评论

0赞 Sanctus 1/8/2020
唯一的解决方案
0赞 l0b0 5/4/2022
不过,你在安装什么?
0赞 Badr B 2/2/2023
唯一对我有用的东西
4赞 Heloisa Rocha 1/23/2020 #5

在 lambda 上使用 psycopg2 的另一种方法(如果您在 Windows 上编程并在 lambda 上使用 python 3.6)

  1. 在您的计算机中创建一个名为 python 的目录
  2. https://pypi.org/project/psycopg2-binary/ 下载库 psycopg2,搜索正确的 paage(amazon linux 是 86_64):psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_x86_64.whl
  3. 将其解压缩到您创建的目录 python,您可以将 7-zip 用于 .whl
  4. 压缩目录python
  5. 现在,在 AWS lambda 面板中,使用您拥有的 python.zip 创建一个层
  6. 最后,将该层添加到您的 lambda 函数中

评论

0赞 Interested_Programmer 8/18/2020
这个解决方案奏效了!我不得不去发布并获取最新的 Python 3.8 的 manylinux x86_64 包,它就像一个魅力!
0赞 Dfranc3373 5/6/2021
这是100%的解决方案!这里还提到了:https://github.com/jkehler/awslambda-psycopg2/issues/51
0赞 Vijay Anand Pandian 6/1/2022
我尝试了以下方法,它奏效了,谢谢psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
12赞 khanna 3/24/2020 #6

天啊!虽然有些答案可能真的很棒而且很有效!只是偶然发现了这个 https://pypi.org/project/aws-psycopg2/,它对我来说就像一个魅力。步骤:

mkdir aws-psycopg2

cd aws-psycopg2

vi get_layer_packages.sh

    export PKG_DIR="python"
    
    rm -rf ${PKG_DIR} && mkdir -p ${PKG_DIR}
    
    docker run --rm -v $(pwd):/foo -w /foo lambci/lambda:build-python3.6 \
        pip install -r requirements.txt --no-deps -t ${PKG_DIR}

vi requirements.txt

    aws-psycopg2

then do :
chmod +x get_layer_packages.sh

./get_layer_packages.sh

zip -r aws-psycopg2.zip .

将此 zip 上传到 AWS Lambda 层!

评论

0赞 deltascience 2/24/2021
先生,您为我节省了很多时间和麻烦,谢谢!
0赞 user2676299 7/20/2021
干净,我还第一次设置了我的本地 docker。感谢
0赞 Hari_pb 10/1/2020 #7

这么多答案,但对我不起作用!请注意,AWS-Lambda 没有预安装大多数与数据库相关的库,因此您需要添加一个包含代码和库的文件才能使其正常工作。请按照以下步骤操作:链接zip

5赞 Rahul Patni 8/9/2021 #8

这是我在尝试的所有方法中发现的最简单的方法:

我在需要 psycopg2 的 lambda 函数中添加了一个 lamdba 层。以下是可用 Lambda 层的列表: https://github.com/jetbridge/psycopg2-lambda-layer

我正在使用无服务器框架,这就是我的 Lambda 函数的样子:

functions:
  example:
    handler: handler.example
    layers:
      - arn:aws:lambda:us-east-1:898466741470:layer:psycopg2-py37:3
    events:
      - http:
          path: example
          method: post
          authorizer: aws_iam
          cors: true

评论

0赞 Shmack 2/2/2022
您是如何为该 python 包生成 arn 的?
0赞 Reuben Khong 8/11/2022 #9

我已经阅读了一些解决方案,包括用户在 Github 上自定义 psychopg2 模块年的解决方案,但问题仍然存在。

我最近通过在 Macbook 上卸载当前的 psychopg2 来解决它,然后去 pip 站点安装它。

  1. 尝试在终端上安装。pip install psycopg2
  2. pip freeze(在包装目录之前重新打包目录中的模块)。
  3. 将其上传到 Lambda。它对我有用。虽然我不得不说这个模块只是一个创可贴解决方案。