Search code examples
pythonaws-lambdaserverless-framework

Serverless framework with python and aws lambda


When i import a function from another file and do the deploy it doesn't work. It gives me: error 500 internal server error. The python requirements works fine, because the hello function doesn't give me an error. But getPrediction doesn't work well

In offline mode all works fine.

My handler.js

try:
    import unzip_requirements
except ImportError:
    pass

import json
import numpy
import scipy
from predictions.make_prediction import make_prediction

def hello(event, context):

    response = {"statusCode": 200, "body": {mod.__name__: mod.__version__ for mod in (numpy, scipy)}}
    return response 

def getPrediction(event, context):
    hola = make_prediction([1,2,3,4,5,6,7])
    response = {"statusCode": 200, "body": json.dumps(hola.tolist())}
    return response 

My serverless.yml

service: enno-searcher
frameworkVersion: '3'

provider:
  name: aws
  runtime: python3.7
  timeout: 29

plugins:
  - serverless-offline
  - serverless-python-requirements

package:
 patterns:
   - '!node_modules/**'
   - '!Lib/**'
   - '!README.md'
   - '!build/**'
   - '!__pycache__/**'
   - '!Include/**'

custom:
  pythonRequirements:
    dockerizePip: true
    zip: true

functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:
          path: /
          method: get
  getPrediction:
    handler: handler.getPrediction
    events:
      - httpApi:
          path: /get-prediction
          method: get

I've tried changing the way I import external functions, but it keeps giving me the same error. maybe i'm doing it wrong

I have also tried not to import functions from other files. I've tried bringing the code from make_prediction to getPrediction, but it keeps giving me an error.


Solution

  • I have managed to solve my problem with serverless framework. After many tests, this is how my files "handler.py" and my "serverless.yml" have stayed

    serverless.yml

    service: enno-searcher
    frameworkVersion: '3'
    
    provider:
      name: aws
      runtime: python3.7
      timeout: 29
      httpApi:
        cors: true
    
    package:
      patterns:
       - '!node_modules/**'
       - '!Lib/**'
       - '!README.md'
       - '!build/**'
       - '!__pycache__/**'
       - '!Include/**'
    
    functions:
      hello:
        handler: handler.hello
        events:
          - httpApi:
              path: /
              method: get
      test:
        handler: handler.test
        events:
          - httpApi:
              path: /test
              method: get
      getprediction:
        handler: handler.getPrediction
        events:
          - httpApi:
              path: /get-prediction
              method: get
    
    plugins:
      - serverless-offline
      - serverless-python-requirements
    
    custom:
      pythonRequirements:
        dockerizePip: non-linux
        zip: true
    

    handler.py

    try:
        import unzip_requirements
    except ImportError:
        pass
    
    import json
    
    def hello(event, context):
        response = {
            "statusCode": 200,
            'headers': {
                'Access-Control-Allow-Origin': '*',
                "Access-Control-Allow-Credentials": True
            },
            "body": 'Searcher Backend v0.0.1'}
        return response
    
    def test(event, context):
        from predictions.make_prediction import make_prediction
        hola = make_prediction([1,2,3,4,5,6,7])
        response = {
            "statusCode": 200,
            'headers': {
                'Access-Control-Allow-Origin': '*',
                "Access-Control-Allow-Credentials": True
            },
            "body": json.dumps(
            hola.tolist()
        )}
        return response 
    
    def getPrediction(event, context):
        try:
            from predictions.make_prediction import make_prediction
            inputPrediction = event['queryStringParameters']['prediction']
            prediction = make_prediction(eval(inputPrediction))
            response = {
                "statusCode": 200,
                'headers': {
                    'Access-Control-Allow-Origin': '*',
                    "Access-Control-Allow-Credentials": True
                },
                "body": json.dumps(
                prediction.tolist()
            )}
            return response
        
        except KeyError as e:
            error_message = f'Faltan los parametros requeridos: {e}'
            response = {
                'statusCode': 400,
                'headers': {
                    'Access-Control-Allow-Origin': '*',
                    "Access-Control-Allow-Credentials": True
                },
                'body': json.dumps({'error': error_message})
            }
            return response
        
        except Exception as e:
            # Captura cualquier otra excepción y devuelve un mensaje de error genérico
            error_message = f'Se produjo un error al procesar la solicitud: {e}'
            response = {
                'statusCode': 500,
                'headers': {
                    'Access-Control-Allow-Origin': '*',
                    "Access-Control-Allow-Credentials": True
                },
                'body': json.dumps({'error': error_message})
            }
            return response
    

    In this way, I have already managed to import functions from other documents. By importing it inside each function, I manage to contain the errors. I've also added try and except to further handle errors. I have also added cors to the APIs.

    In addition, I have added many more functions (which I have not put here), with the same structure as the "getPrediction" function. They have all worked perfectly for me.