如何将模块从自定义程序包正确导入到AWS Lambda函数中?

问题描述

我是 AWS 的新手,需要一些建议。我有一个包含多个AWS Lambda函数的项目。就我而言,有四个,它们位于functions文件夹中。他们都需要使用数据库连接。因此,我决定将与数据库相关的代码放在一个单独的名为databases的程序包中,并在AWS Lambda Layers中使用它。如您所见,databases包有两个模块。从文档中可以了解,我需要将我的软件包存档并放入AWS Lambda Layers中。但是,此程序包的地址更改。由于AWS认将其放置在/opt目录中。我有点困惑。如何从自定义包中正确导入模块到AWS Lambda函数中,以使其在本地和生产环境中正常工作?

我项目的结构如下:

src
   functions
      create_user_information
         __init__.py
         lambda_function.py
      update_user_information
         __init__.py
         lambda_function.py
      get_user_information
         __init__.py
         lambda_function.py
      delete_user_information
         __init__.py
         lambda_function.py
   layers
      databases
         __init__.py
         cassandra.py
         postgresql.py
         requirements.txt
template.yaml
venv
   bin
      ...
   include
   lib
      ...

lambda_function.py:

from src.layers.databases import cassandra


cassandra_db_session = None
cassandra_db_username = 'your-username'
cassandra_db_password = 'your-password'
cassandra_db_endpoints = ['your-endpoint']
cassandra_db_port = 9142


def lambda_handler(event,context):
    global cassandra_db_session
    if not cassandra_db_session:
        cassandra_db_session = cassandra.create_session(
            cassandra_db_username,cassandra_db_password,cassandra_db_endpoints,cassandra_db_port
        )
    # Some business logic.
    # ...
    return "AWS Lambda function finished."

template.yaml:

AWstemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: User information Service
Globals:
    Function:
        Timeout: 10
Resources:
    Databases:
        Type: AWS::Serverless::LayerVersion
        Properties:
            LayerName: Databases
            Description:
            ContentUri:
            CompatibleRuntimes:
                - python3.8
            LicenseInfo: MIT
            RetentionPolicy: Retain
    GetUserinformation:
        Type: AWS::Serverless::Function
        Properties:
            FunctionName: GetUserinformation
            Description:
            CodeUri: src/functions/get_user_information
            Handler: lambda_function.lambda_handler
            Runtime: python3.8
            Layers:
                - !Ref Databases
    createuserinformation:
        Type: AWS::Serverless::Function
        Properties:
            FunctionName: createuserinformation
            Description:
            CodeUri: src/functions/create_user_information
            Handler: lambda_function.lambda_handler
            Runtime: python3.8
            Layers:
                - !Ref Databases
    UpdateUserinformation:
        Type: AWS::Serverless::Function
        Properties:
            FunctionName: UpdateUserinformation
            Description:
            CodeUri: src/functions/update_user_information
            Handler: lambda_function.lambda_handler
            Runtime: python3.8
            Layers:
                - !Ref Databases
    DeleteUserinformation:
        Type: AWS::Serverless::Function
        Properties:
            FunctionName: DeleteUserinformation
            Description:
            CodeUri: src/functions/delete_user_information
            Handler: lambda_function.lambda_handler
            Runtime: python3.8
            Layers:
                - !Ref Databases
Outputs:
    DatabasesARN:
        Value: !Ref Databases
        Description: Databases ARN
        Export:
            Name: databases-arn

解决方法

假设您已打包# assume 'databases' is the installation name of your pkg from databases import cassandra 并将其正确安装在图层中,那么导入将非常简单:

src
  1. 您的软件包必须是“可安装的”,以上代码无法正常工作。网上有很多关于如何正确执行操作的参考。

重要的是要注意,您不需要遵循这种方法(除建议之外)。您可以打包整个# don't use relative imports in lambda because the change to opt/ from src.layers.databases import cassandra 文件夹,然后将其作为lambda函数上传,因此您可以按以下方式使用:

diskutil resetUserPermissions / `id -u`

当前问题不是由任何类型的“目录更改”引起的,而是由错误的包装引起的。