使用 psycopg2 和 Lambda 更新 Redshift (Python)
Using psycopg2 with Lambda to Update Redshift (Python)
我正在尝试使用 python 从 Lambda 函数更新 Redshift。为此,我试图合并 2 个代码片段。当我 运行 分开时,这两个片段都可以使用。
从 PyDev 更新 Redshift for Eclipse
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()
接收上传到 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”。
是什么导致了这个问题?当我使用 3.4 时 Lambda 使用 Python 2.7 是否重要?我在 Windows 机器上压缩我的文件内容有关系吗?有没有人能够从 lambda 成功连接到 Redshift?
为了使其正常工作,您需要使用静态链接的 libpq.so
库构建 psycopg2
。查看此存储库 https://github.com/jkehler/awslambda-psycopg2。它已经构建了 psycopg2 包并说明了如何自己构建它。
回到您的问题:
是什么导致了这个问题?
psycopg2
需要为 Linux.
编译静态链接库
当我使用 3.4 时 Lambda 使用 Python 2.7 是否重要?
是的,lambda 只支持 2.7 版本。只需创建虚拟环境并在其中安装所有必需的包。
我在 Windows 机器上压缩我的文件内容重要吗?
只要您压缩的所有库都可以 运行 Linux 它不会
有没有人能够从 lambda 成功连接到 Redshift?
是的。
我刚遇到同样的问题。我偶然发现了另一个答案中提到的相同 github project,该答案解释了如下问题:
由于 AWS Lambda 在 AMI 映像中缺少所需的 PostgreSQL 库,我们需要使用 PostgreSQL libpq.so 库静态编译 psycopg2 linked libpq 库而不是默认动态 link.
这已在之前的回答中提到,我开始按照说明使用静态 linked PostgreSQL 库为自己构建一个 psycopg2 版本。不过,我找到了一个更简单的选择。我在 psycopg2 github page 上注意到以下内容:
您还可以通过从 PyPI 安装 psycopg2-binary 包来获得独立包,不需要编译器或外部库:
$ pip install psycopg2-binary
二进制包是开发和测试的实用选择,但在生产中建议使用从源构建的包。
当我 pip 安装 psycopg2-binary 包并将其包含在我的 requirements.txt 文件中时,我能够从 lambda 函数完美地连接到我的 postgresql 数据库。我正在使用我强烈推荐的 chalice。我意识到 psycopg2 建议不要将二进制版本用于生产,但我没有看到使用二进制版本或自己编译和静态 linking 之间的巨大差异。如果我错了,请有人纠正我。
假设您的打包是正确的,no module named psycopg2
错误通常表示您的 psycopg2 部署的二进制文件对于您的目标 OS 或 Python 版本不正确。
对于 Lambdas,我们发现 psycopg2 binary works (using manylinux_x86_64). There is a reported risk of segfault due to the presence of competing libssl binaries 尽管我们还没有找到它。
(这基本上是对上面 jshammon 的回答的+1)
"proper solution" 可能是 jkehlers 专门为 Lambda 重新编译只缺少 lib_pq.so
,但它目前不支持 ssl+py3.7 而我们也是 Windows 自己重新编译。
要将 psycopg2 与 aws lambda 一起使用,请使用 import aws-psycopg2
由于aws支持psycopg2,但是导入psycopg2的方式有点不同,因为aws本身有一个针对psycopg2的编译库,所以我们需要导入使用aws-psycopg2
在 lambda 上使用 psycopg2 的另一种方法(如果您在 windows 上编程并在 lambda 上使用 python 3.6)
- 在您的机器上创建一个名为 python
的目录
- 从 https://pypi.org/project/psycopg2-binary/ 下载 lib psycopg2,搜索正确的包(亚马逊 linux 是 86_64):psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_x86_64.whl
- 将其解压缩到您创建的目录 python,您可以使用 7-zip for .whl
- 压缩目录 python
- 现在在 AWS lambda 面板中,使用您拥有的 python.zip 创建一个层
- 最后将该层添加到您的 lambda 函数中
天哪!虽然有些答案可能真的很棒并且有效!刚刚偶然发现了这个 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
然后做:
chmod +x get_layer_packages.sh
./get_layer_packages.sh
zip -r aws-psycopg2.zip .
将此 zip 上传到 AWS Lambda 层!
这么多答案,但对我没有用!请注意 AWS-Lambda 没有预装大部分 DB-related 库,因此您需要添加一个包含代码和库的 zip
文件才能使其正常工作。请按照此处的步骤操作:Link
这是我尝试过的所有方法中发现的最简单的方法:
我在需要 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
我正在尝试使用 python 从 Lambda 函数更新 Redshift。为此,我试图合并 2 个代码片段。当我 运行 分开时,这两个片段都可以使用。
从 PyDev 更新 Redshift for Eclipse
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()
接收上传到 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”。
是什么导致了这个问题?当我使用 3.4 时 Lambda 使用 Python 2.7 是否重要?我在 Windows 机器上压缩我的文件内容有关系吗?有没有人能够从 lambda 成功连接到 Redshift?
为了使其正常工作,您需要使用静态链接的 libpq.so
库构建 psycopg2
。查看此存储库 https://github.com/jkehler/awslambda-psycopg2。它已经构建了 psycopg2 包并说明了如何自己构建它。
回到您的问题:
是什么导致了这个问题?
psycopg2
需要为 Linux.
当我使用 3.4 时 Lambda 使用 Python 2.7 是否重要?
是的,lambda 只支持 2.7 版本。只需创建虚拟环境并在其中安装所有必需的包。
我在 Windows 机器上压缩我的文件内容重要吗?
只要您压缩的所有库都可以 运行 Linux 它不会
有没有人能够从 lambda 成功连接到 Redshift?
是的。
我刚遇到同样的问题。我偶然发现了另一个答案中提到的相同 github project,该答案解释了如下问题:
由于 AWS Lambda 在 AMI 映像中缺少所需的 PostgreSQL 库,我们需要使用 PostgreSQL libpq.so 库静态编译 psycopg2 linked libpq 库而不是默认动态 link.
这已在之前的回答中提到,我开始按照说明使用静态 linked PostgreSQL 库为自己构建一个 psycopg2 版本。不过,我找到了一个更简单的选择。我在 psycopg2 github page 上注意到以下内容:
您还可以通过从 PyPI 安装 psycopg2-binary 包来获得独立包,不需要编译器或外部库:
$ pip install psycopg2-binary
二进制包是开发和测试的实用选择,但在生产中建议使用从源构建的包。
当我 pip 安装 psycopg2-binary 包并将其包含在我的 requirements.txt 文件中时,我能够从 lambda 函数完美地连接到我的 postgresql 数据库。我正在使用我强烈推荐的 chalice。我意识到 psycopg2 建议不要将二进制版本用于生产,但我没有看到使用二进制版本或自己编译和静态 linking 之间的巨大差异。如果我错了,请有人纠正我。
假设您的打包是正确的,no module named psycopg2
错误通常表示您的 psycopg2 部署的二进制文件对于您的目标 OS 或 Python 版本不正确。
对于 Lambdas,我们发现 psycopg2 binary works (using manylinux_x86_64). There is a reported risk of segfault due to the presence of competing libssl binaries 尽管我们还没有找到它。 (这基本上是对上面 jshammon 的回答的+1)
"proper solution" 可能是 jkehlers 专门为 Lambda 重新编译只缺少 lib_pq.so
,但它目前不支持 ssl+py3.7 而我们也是 Windows 自己重新编译。
要将 psycopg2 与 aws lambda 一起使用,请使用 import aws-psycopg2
由于aws支持psycopg2,但是导入psycopg2的方式有点不同,因为aws本身有一个针对psycopg2的编译库,所以我们需要导入使用aws-psycopg2
在 lambda 上使用 psycopg2 的另一种方法(如果您在 windows 上编程并在 lambda 上使用 python 3.6)
- 在您的机器上创建一个名为 python 的目录
- 从 https://pypi.org/project/psycopg2-binary/ 下载 lib psycopg2,搜索正确的包(亚马逊 linux 是 86_64):psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_x86_64.whl
- 将其解压缩到您创建的目录 python,您可以使用 7-zip for .whl
- 压缩目录 python
- 现在在 AWS lambda 面板中,使用您拥有的 python.zip 创建一个层
- 最后将该层添加到您的 lambda 函数中
天哪!虽然有些答案可能真的很棒并且有效!刚刚偶然发现了这个 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
然后做: chmod +x get_layer_packages.sh
./get_layer_packages.sh
zip -r aws-psycopg2.zip .
将此 zip 上传到 AWS Lambda 层!
这么多答案,但对我没有用!请注意 AWS-Lambda 没有预装大部分 DB-related 库,因此您需要添加一个包含代码和库的 zip
文件才能使其正常工作。请按照此处的步骤操作:Link
这是我尝试过的所有方法中发现的最简单的方法:
我在需要 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