首页 > 解决方案 > 如何将自定义包中的模块正确导入 AWS Lambda 函数?

问题描述

我是AWS新手,需要一些建议。我有一个包含多个 AWS Lambda 函数的项目。就我而言,有四个,它们位于functions文件夹中。他们都需要使用数据库连接。所以我决定将与数据库相关的代码放在一个单独的包中databases,并在 AWS Lambda 层中使用它。如您所见,该databases软件包有两个模块。正如我从文档中了解到的,我需要归档我的包并将其放入 AWS Lambda 层。但是,这个包的地址发生了变化。/opt由于 AWS默认将其放在目录中。我有点困惑。如何将自定义包中的模块正确导入 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."

模板.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

标签: pythonamazon-web-servicesaws-lambdaaws-lambda-layers

解决方案


假设您已经databases在图层中正确打包并安装了它,那么您的导入将非常简单:

# assume 'databases' is the installation name of your pkg
from databases import cassandra  
  1. 您的软件包必须是“可安装的”才能使上面的代码正常工作,但它看不到。网上有很多关于如何正确操作的参考资料。

重要的是要注意您不需要遵循这种方法(除了被推荐)。您可以打包整个src文件夹并作为 lambda 函数上传,因此您可以按如下方式使用:

# don't use relative imports in lambda because the change to opt/
from src.layers.databases import cassandra  

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


推荐阅读