使用psycopg2和Lambda来更新Redshift(Python)

aws*_*ion 10 python amazon-web-services amazon-redshift aws-sdk aws-lambda

我试图使用python从Lambda函数更新Redshift.为此,我试图合并两个代码片段.当我单独运行它们时,两个片段都是有效的.

  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()
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

由于这两个段都有效,我尝试将它们组合起来,以便在将文件上传到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
Run Code Online (Sandbox Code Playgroud)

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

pip install psycopg2 -t \lambda_function1
Run Code Online (Sandbox Code Playgroud)

我收到以下反馈:

Collecting psycopg2
  Using cached psycopg2-2.6.1-cp34-none-win_amd64.whl
Installing collected packages: psycopg2
Successfully installed psycopg2-2.6.1 
Run Code Online (Sandbox Code Playgroud)

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

Unable to import module 'lambda_function1': No module named _psycopg 
Run Code Online (Sandbox Code Playgroud)

当我查看图书馆时,唯一名为"_psycopg"的是"_psycopg.pyd".

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

Vor*_*Vor 15

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

回到你的问题:

是什么导致了这个问题?

psycopg2 需要构建一个使用静态链接库编译的Linux.

当我使用3.4时,Lambda使用Python 2.7是否重要?

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

我在Windows机器上压缩文件内容是否重要?

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

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

是.


kha*_*nna 8

好家伙!虽然有些答案可能真的很棒而且有效!只是偶然发现了这个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}
Run Code Online (Sandbox Code Playgroud)

vi 要求.txt

aws-psycopg2
Run Code Online (Sandbox Code Playgroud)

然后做: chmod +x get_layer_packages.sh

./get_layer_packages.sh

zip -r aws-psycopg2.zip 。

将此 zip 上传到 AWS Lambda 层!


小智 7

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

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

这在前面的答案中已经提到,我开始按照说明进行操作,以使用静态链接的PostgreSQL库构建自己的psycopg2版本。我发现了一个更容易的选择。我在psycopg2 github页面上注意到以下内容:

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

$ pip install psycopg2-binary

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

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

  • 我很好奇你正在使用什么操作系统。我的猜测是,只有当您运行“pip install psycopg2-binary”的平台与 AWS Lambda 二进制兼容时,这才有效。 (2认同)

小智 6

要将psycopg2与 aws lambda 一起使用,请使用import aws-psycopg2

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


小智 5

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

在需要 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
Run Code Online (Sandbox Code Playgroud)