web-dev-qa-db-fra.com

Utilisation de psycopg2 avec Lambda pour mettre à jour Redshift (Python)

J'essaie de mettre à jour Redshift à partir d'une fonction Lambda en utilisant python. Pour ce faire, j'essaye de combiner 2 fragments de code. Les deux fragments sont fonctionnels lorsque je les exécute séparément.

  1. Mise à jour de Redshift depuis PyDev pour 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()
    
  2. Réception de contenu téléchargé dans le compartiment S3 (modèle prédéfini disponible sur 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
    

Puisque ces deux segments fonctionnaient, j'ai essayé de les combiner afin de pouvoir mettre à jour Redshift lors du téléchargement d'un fichier vers s3:

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

Étant donné que j'utilise une bibliothèque externe, je dois créer un package de déploiement. J'ai créé un nouveau dossier (lambda_function1) et déplacé mon fichier .py (lambda_function1.py) dans ce dossier. J'ai exécuté la commande suivante pour installer psycopg2 dans ce dossier:

pip install psycopg2 -t \lambda_function1

Je reçois les commentaires suivants:

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

J'ai ensuite zippé le contenu du répertoire. Et téléchargé ce Zip sur ma fonction lambda. Lorsque je télécharge un document dans le compartiment surveillé par la fonction, je reçois l'erreur suivante dans mon journal cloudwatch:

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

Quand je regarde dans la bibliothèque, la seule chose nommée "_psycopg" est "_psycopg.pyd".

Quelle est la cause de ce problème? Est-il important que Lambda utilise Python 2.7 lorsque j'utilise 3.4? Est-il important que j'ai compressé le contenu de mon fichier sur une machine Windows? Quelqu'un a-t-il réussi à se connecter à Redshift à partir de lambda?

12
awsQuestion

Pour que cela fonctionne, vous devez créer psycopg2 Avec la bibliothèque libpq.so Liée statiquement. Découvrez ce dépôt https://github.com/jkehler/awslambda-psycopg2 . Il a déjà construit le paquet psycopg2 et des instructions pour le construire vous-même.

Retour à vos questions:

Quelle est la cause de ce problème?

psycopg2 Doit être compilé et compilé avec des bibliothèques liées statiquement pour Linux.

Est-il important que Lambda utilise Python 2.7 lorsque j'utilise 3.4?

Oui, lambda ne prend en charge que la version 2.7. Créez simplement un environnement virtuel et installez-y tous les packages nécessaires.

Est-il important que j'ai compressé le contenu de mon fichier sur une machine Windows?

Tant que toutes les bibliothèques que vous avez compressées peuvent fonctionner sous Linux, cela ne fonctionne pas

Quelqu'un a-t-il réussi à se connecter à Redshift à partir de lambda?

oui.

16
Vor

Je viens de rencontrer ce même problème. Je suis tombé sur le même projet github qui a été noté dans l'autre réponse qui expliquait le problème comme suit:

En raison d'AWS Lambda manquant les bibliothèques PostgreSQL requises dans l'image AMI, nous avions besoin de compiler psycopg2 avec la bibliothèque libpq.so de PostgreSQL libpq liée statiquement à la place du lien dynamique par défaut.

Cela a été noté dans la réponse précédente, et j'ai commencé à suivre les instructions pour créer moi-même une version de psycopg2 avec une bibliothèque PostgreSQL liée statiquement. J'ai trouvé une option beaucoup plus simple. J'ai remarqué sur la page github psycopg2 ce qui suit:

Vous pouvez également obtenir un package autonome, ne nécessitant pas de compilateur ou de bibliothèques externes, en installant le package psycopg2-binary de PyPI:

$ pip install psycopg2-binary

Le package binaire est un choix pratique pour le développement et les tests mais en production, il est conseillé d'utiliser le package construit à partir des sources.

Lorsque j'ai installé le paquet psycopg2-binary et l'ai inclus dans mon fichier requirements.txt, j'ai pu me connecter sans problème à ma base de données postgresql à partir d'une fonction lambda. J'utilise calice que je recommande fortement. Je me rends compte que psycopg2 recommande de ne pas utiliser la version binaire pour la production, mais je ne vois pas de différence énorme entre l'utilisation de la version binaire ou la compilation et la liaison statique vous-même. Quelqu'un, s'il vous plaît, corrigez-moi si je me trompe.

7
jshammon

Pour utiliser psycopg2 avec aws lambda, utilisez import aws-psycopg2

Comme aws prend en charge psycopg2, mais la façon d'importer psycopg2 est un peu différente car aws a lui-même une bibliothèque compilée pour psycopg2, nous devons donc importer en utilisant aws-psycopg2

2
Sumit Chhabra

Une autre façon d'utiliser psycopg2 sur lambda (si vous programmez sur windows et utilisez python 3.6 sur lambda)

  1. Dans votre machine, créez un répertoire appelé python
  2. Téléchargez la lib psycopg2 depuis https://pypi.org/project/psycopg2-binary/ , recherchez le bon paquet (Amazon linux est 86_64): psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_x86_64 .whl
  3. Décompressez-le dans le répertoire python que vous avez créé, vous pouvez utiliser 7-Zip pour .whl
  4. Zip le python directoire
  5. Maintenant, dans le panneau AWS lambda, créez une couche avec le python.Zip que vous avez
  6. Enfin, ajoutez la couche à votre fonction lambda
0
Heloisa Fernanda

oh mec! alors que certaines des réponses peuvent être vraiment géniales et fonctionnent! Je suis juste tombé sur cela https://pypi.org/project/aws-psycopg2/ et cela a fonctionné comme un charme pour moi. pas :

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

puis faites: chmod + x get_layer_packages.sh

./get_layer_packages.sh

Zip -r aws-psycopg2.Zip.

téléchargez ce Zip sur la couche AWS Lambda!

0
khanna

En supposant que votre emballage est correct, le no module named psycopg2 L'erreur indique généralement que le ou les fichiers binaires de votre déploiement psycopg2 sont incorrects pour votre système d'exploitation cible ou Python.

Pour Lambdas, nous avons trouvé que le binaire psycopg2 fonctionne (en utilisant manylinux_x86_64). Il existe un risque signalé de segfault en raison de la présence de binaires libssl bien que nous ne les ayons pas encore. (il s'agit essentiellement d'un +1 pour la réponse de jshammon ci-dessus)

La "bonne solution" est probablement jkehlers recompiler spécifiquement pour Lambda manquant seulement lib_pq.so, mais il ne supporte pas actuellement ssl + py3.7 et nous sommes trop Windows pour le recompiler nous-mêmes.

0
David Stannard