【问题标题】:Is it possible to add paths to the PATH environment variable through serverless.yml?是否可以通过 serverless.yml 将路径添加到 PATH 环境变量?
【发布时间】:2019-01-11 18:47:51
【问题描述】:

当我创建 AWS Lambda 层时,当 AWS Lambda 执行时,我的 zip 文件的所有内容/模块都会转到 /opt/。这很容易变得麻烦和令人沮丧,因为我必须在我的所有 lambdas 上使用绝对导入。示例:

import json
import os
import importlib.util
spec = importlib.util.spec_from_file_location("dynamodb_layer.customer", "/opt/dynamodb_layer/customer.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

def fetch(event, context):

    CustomerManager = module.CustomerManager
    customer_manager = CustomerManager()

    body = customer_manager.list_customers(event["queryStringParameters"]["acquirer"])

    response = {
        "statusCode": 200,
        "headers": {
            "Access-Control-Allow-Origin": "*"
        },
        "body": json.dumps(body)
    }

    return response

所以我想知道,是否可以通过 serverless.yml 预先将这些 /opt/paths 添加到 PATH 环境变量中?这样一来,我就可以from dynamodb_layer.customer import CustomerManager,而不是那种怪异的丑陋。

【问题讨论】:

    标签: python amazon-web-services aws-lambda aws-lambda-layers


    【解决方案1】:

    我有 Python3.6 运行时的 Lambda 层。我的 my_package.zip 结构是:

    my_package.zip
     - python
       - lib
         - python3.6
           - site-packages
             - customer
    

    所有依赖项都在项目根目录的build 文件夹中: 例如build/python/lib/python3.6/site-packages/customer

    我的 serverless.yml 的相关部分

    layers:
      my_package:
        path: build             
        compatibleRuntimes:     
          - python3.6
    

    在我的 Lambda 中,我像导入任何其他包一样导入我的包: import customer

    【讨论】:

    • 你知道有没有办法在 serverless 中设置路径?我有一堆文件,我不想压缩到特定的目录结构中,但我希望它们以/opt/python/lib/python3.6/site-packages/shared 结尾。有没有办法在 git 中不将它们组织在相同的目录结构中?
    • @Craig 您的构建脚本可以在将目录打包成 zip 文件之前以它认为合适的任何方式操作目录。这通常称为“分期”。在这种情况下,您的构建将创建一个名为“python”的目录,然后将所需的文件和 package-dies 复制到其中,然后创建 zip 并将其作为层上传。例如,请参阅我的答案!
    【解决方案2】:

    您是否尝试过设置 PYTHONPATH 环境变量? https://stackoverflow.com/a/5944201/6529424

    您是否尝试过添加到 sys.path? https://stackoverflow.com/a/12257807/6529424

    【讨论】:

    • 这些不是使用 Lambda 层添加可导入模块和包的惯用方法。见下文。
    【解决方案3】:

    在 zip 存档中,模块需要放在 python 子目录中,以便在 Lambda 中将其作为层提取时,它位于 /opt/python。这样你就可以直接导入你的模块而不需要importlib

    documented here 或查看 AWS 开发布道者的 this detailed blogpost 了解更多信息。

    【讨论】:

    • 您提供的链接似乎不够明确,无法满足我使用自己的软件包的需要 - 因此我在下面自己的答案中更直接地写了一些东西,
    • 对你有好处,伙计。不过,您不必到处乱发垃圾邮件...
    • 抱歉,@milan 让您感到恼火 - 我自己也遇到了这个问题,我想我会添加一些额外的信息以供其他人使用。这绝不是“垃圾邮件”或自我推销。我试图在应得的地方给予信任。如果您有 SO 问题的新细节,我相信您也会这样做。
    【解决方案4】:

    PYTHONPATH 变量的设置不是必需的,只要将项目正确放置在 zip 文件中即可。

    简单的模块和包目录,这些应该放在“python”目录中,然后将整个 python/ 放入 zip 文件中,以作为层上传到 AWS。不要忘记为图层添加“兼容的运行时”(例如 Python 3.6、3.7、3.8 ...)设置。

    举个例子:

    python/
    - my_module.py
    - my_package_dir
    -- __init__.py
    -- package_mod_1.py
    -- package_mod_2.py
    

    然后将其包含在 zip 文件中。

    zip -r my_layer_zip.zip python/
    

    当作为层访问时,可以毫不费力地导入模块:

    ....
    import my_module
    from my_package.package_mod_2 import mod_2_function
    ....
    

    如果您查看“/opt/python/”,您可以从 lambda 中看到包结构,它将显示 my_module.py、my_package/ 等,这很容易使用 AWS Lambda 测试函数进行测试,假设层附加到函数上(否则代码会出错)

    import json
    import os
    
    def lambda_handler(event, context):
        # TODO implement
    
        dir_list = os.listdir('/opt/python/')
    
        return {
            'statusCode': 200,
            'body': json.dumps('Hello from Lambda!'),
            'event': json.dumps(event),
            '/opt/python/': dir_list
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-28
      • 1970-01-01
      • 2020-06-08
      • 2020-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      相关资源
      最近更新 更多