提问人:awsQuestion 提问时间:4/14/2016 最后编辑:hjpotter92awsQuestion 更新时间:11/17/2023 访问量:56040
将 psycopg2 与 Lambda 结合使用以更新 Redshift (Python)
Using psycopg2 with Lambda to Update Redshift (Python)
问:
我正在尝试使用 python 从 Lambda 函数更新 Redshift。为此,我正在尝试组合 2 个代码片段。当我单独运行它们时,这两个片段都可以正常工作。
从 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()
接收上传到 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?
答:
为此,您需要使用静态链接库进行构建。查看此 repo https://github.com/jkehler/awslambda-psycopg2。它已经构建了 psycopg2 包,并说明了如何自己构建它。psycopg2
libpq.so
回到您的问题:
是什么导致了这个问题?
psycopg2
需要使用适用于 Linux 的静态链接库进行构建和编译。
当我使用 Python 3.4 时,Lambda 使用 Python 2.7 有关系吗?
是的,lambda 仅支持 2.7 版本。只需创建虚拟环境并在其中安装所有必要的软件包即可。
我在 Windows 机器上压缩文件内容有关系吗?
只要您压缩的所有库都可以在 Linux 上运行,它就不能
有没有人能够从 lambda 成功连接到 Redshift?
是的。
评论
import psycopg2
conn_string = "dbname='............ etc
conn = psycopg2.connect(conn_string)
cursor = conn.cursor()
cursor.execute("Update Query")
DatabaseError: SSL SYSCALL error: Operation timed out
我刚刚遇到了同样的问题。我偶然发现了另一个答案中提到的同一个 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 建议不要将二进制版本用于生产,但我看不出使用二进制版本或自己编译和静态链接之间没有太大区别。如果我错了,有人请纠正我。
评论
pip install psycopg2-binary
假设您的打包正确,该错误通常表示 psycopg2 部署的二进制文件对于您的目标操作系统或 Python 版本不正确。no module named psycopg2
对于 Lambdas,我们发现 psycopg2 二进制文件有效(使用 manylinux_x86_64)。据报道,由于存在相互竞争的 libssl 二进制文件,存在段错误的风险,尽管我们还没有。 (这基本上是 jshammon 上面答案的 +1)
“正确的解决方案”可能是专门针对 Lambda 的 jkehlers 重新编译,仅缺少 ,但它目前不支持 ssl+py3.7,而且我们太 Windows 了,无法自己重新编译它。lib_pq.so
要将 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/ 下载库 psycopg2,搜索正确的 paage(amazon linux 是 86_64):psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_x86_64.whl
- 将其解压缩到您创建的目录 python,您可以将 7-zip 用于 .whl
- 压缩目录python
- 现在,在 AWS lambda 面板中,使用您拥有的 python.zip 创建一个层
- 最后,将该层添加到您的 lambda 函数中
评论
psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
天啊!虽然有些答案可能真的很棒而且很有效!只是偶然发现了这个 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 层!
评论
这么多答案,但对我不起作用!请注意,AWS-Lambda 没有预安装大多数与数据库相关的库,因此您需要添加一个包含代码和库的文件才能使其正常工作。请按照以下步骤操作:链接zip
这是我在尝试的所有方法中发现的最简单的方法:
我在需要 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
评论
我已经阅读了一些解决方案,包括用户在 Github 上自定义 psychopg2 模块年的解决方案,但问题仍然存在。
我最近通过在 Macbook 上卸载当前的 psychopg2 来解决它,然后去 pip 站点安装它。
- 尝试在终端上安装。
pip install psycopg2
- pip freeze(在包装目录之前重新打包目录中的模块)。
- 将其上传到 Lambda。它对我有用。虽然我不得不说这个模块只是一个创可贴解决方案。
评论