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をラムダ関数にアップロードしました。関数が監視するバケットにドキュメントをアップロードすると、cloudwatchログに次のエラーが表示されます。
Unable to import module 'lambda_function1': No module named _psycopg
ライブラリを見ると、「_ psycopg」という名前の唯一のものは「_psycopg.pyd」です。
この問題の原因は何ですか? LambdaがPython 2.7を使用するときに3.4を使用することは重要ですか?Windowsマシンでファイルの内容を圧縮したことは重要ですか?誰もがlambdaからRedshiftに正常に接続できましたか?
これを機能させるには、psycopg2
静的リンクlibpq.so
図書館。このリポジトリをチェックしてください https://github.com/jkehler/awslambda-psycopg2 。それはすでにpsycopg2パッケージをビルドし、それを自分でビルドする方法を示しています。
あなたの質問に戻る:
この問題の原因は何ですか?
psycopg2
は、Linux用の静的にリンクされたライブラリでコンパイルされたビルドを作成する必要があります。
LambdaがPython 2.7を使用するときに3.4を使用することは重要ですか?
はい、ラムダは2.7バージョンのみをサポートしています。仮想環境を作成し、そこに必要なすべてのパッケージをインストールするだけです。
Windowsマシンでファイルの内容を圧縮したことは重要ですか?
圧縮したすべてのライブラリをLinuxで実行できる限り、
誰かがラムダからRedshiftに正常に接続できましたか?
はい。
私はこの同じ問題に出くわしました。次のように問題を説明した他の回答で指摘された同じ githubプロジェクト に偶然出会いました:
AWS LambdaにAMIイメージに必要なPostgreSQLライブラリがないため、デフォルトの動的リンクの代わりにPostgreSQL libpq.soライブラリを静的にリンクしたlibpqライブラリを使用してpsycopg2をコンパイルする必要がありました。
これは前の回答で指摘されており、私は静的にリンクされたPostgreSQLライブラリを備えたpsycopg2のバージョンを自分で構築するための指示に従い始めました。しかし、はるかに簡単なオプションを見つけました。 psycopg2 github page で次のことに気付きました:
PyPI:からpsycopg2-binaryパッケージをインストールすることで、コンパイラや外部ライブラリを必要としないスタンドアロンパッケージを取得することもできます。
$ pip install psycopg2-binary
バイナリパッケージは、開発とテストの実用的な選択肢ですが、本番環境では、ソースからビルドされたパッケージを使用することをお勧めします。
Psycopg2-binaryパッケージをpipインストールして私のrequirements.txtファイルに含めたところ、ラムダ関数からpostgresqlデータベースに問題なく接続できました。私は chalice を使用していますが、これを強くお勧めします。 psycopg2は本番環境ではバイナリバージョンを使用しないことをお勧めしますが、バイナリバージョンを使用するか、自分でコンパイルして静的にリンクするかには大きな違いはありません。私がそれについて間違っているなら誰かが私を訂正してください。
Awsラムダでpsycopg2を使用するには、import aws-psycopg2を使用します
Awsはpsycopg2をサポートしますが、aws自体にpsycopg2のコンパイル済みライブラリがあるため、psycopg2をインポートする方法は少し異なります。したがって、インポートする必要があるのはaws-psycopg2を使用することです。
ラムダでpsycopg2を使用する別の方法(Windowsでプログラミングし、python 3.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
次に行う:chmod + x get_layer_packages.sh
./get_layer_packages.sh
Zip -r aws-psycopg2.Zip。
このZipをAWS Lambdaレイヤーにアップロードしてください!
パッケージが正しいと仮定すると、no module named psycopg2
エラーは通常、psycopg2デプロイメントのバイナリファイルがターゲットOSまたはPythonバージョンの場合)に正しくないことを示します。
ラムダの場合、 psycopg2バイナリ が機能することがわかりました(manylinux_x86_64を使用)。まだ報告されていませんが、競合する libssl binaries が存在するため、 segfault のリスクが報告されています。 (これは基本的に上記のjshammonの回答の+1です)
「適切な解決策」はおそらく jkehlers Lambdaがlib_pq.so
、しかしそれは現在ssl + py3.7をサポートしておらず、私たちは自分たちでそれを再コンパイルするにはWindowsです。