【问题标题】:How to share code in serverless with Python properly?如何在无服务器中与 Python 正确共享代码?
【发布时间】:2020-07-24 06:06:45
【问题描述】:

我正在尝试寻找使用 Python 进行健壮无服务器开发的最佳方法。该项目使用无服务器框架分为多个服务,并在 monorepo 中进行版本控制。这是我想要的结构:

  • service_1/
    • serverless.yml
    • handler.py
  • service_2/
    • serverless.yml
    • handler.py
  • 共享
    • module_a.py
    • module_b.py

module_a 和 module_b 包含共享逻辑,这两个服务都应该可用。到目前为止,我找到了两种方法:将共享代码包装在可安装的包中,并通过 pip 将其注入服务或将共享代码作为层提供。两种解决方案都有缺陷,最重要的是无法快速开发应用程序,因为任何更改都需要 pip。 我注意到这个问题在 Node.js 中得到了解决,还有很多关于 Python 的未解决的问题。

the plugin - serverless-package-common,它似乎可以解决这个问题,但是,它看起来不像是优先的方法。

感谢任何形式的帮助。

【问题讨论】:

  • 我对 Node.js 不熟悉。那里的问题究竟是如何解决的?你能链接一些未回答的问题吗?尽管没有公认的答案,但它们可能包含有用的信息。
  • 嗯,我应该更具体地说明未回答的问题 - 我的意思是像我在脑海中提出的问题。在 Node.js 中,共享代码可能会像 this post 一样被解析。

标签: python aws-lambda serverless


【解决方案1】:

也许您可以考虑使用 Lambda 层。您可以在此处找到快速指南:link

让我举一个简单的例子。此示例有两个无服务器项目 - library 具有共享代码和 service 具有服务代码。

  1. library - 该项目应具有以下文件结构。您在该项目的根目录中有serverless.yml,另一个文件夹将作为模块导出。 python 将被链接并让 lambda 在您将 lambda 与 python 一起使用时找到您的模块。
./
└ serverless.yml
└ common/
    └ python/
        └ Common.py

serverless.yml - 如您所见,文件夹common 在此处明确声明为导出。请注意,层名称Common 会在资源中重复使用,无服务器框架会自动将其与资源引用匹配。

service: library
  provider:
    name: aws
    runtime: python3.7
    stage: dev
    region: ap-northeast-1
  layers:
    Common:
      path: common
  resources:
    Outputs:
      CommonLayerExport:
        Value:
          Ref: CommonLambdaLayer
        Export:
          Name: CommonLambdaLayer

common/python/Common.py(printException 是共享函数的一个例子,将在另一个项目中使用)

import sys
import traceback
import os

def printException(exception, writer=None):
    if writer is None:
      writer = print
    top = traceback.extract_tb(sys.exc_info()[2])[-1]
    writer(", ".join([type(exception).__name__, str(sys.exc_info()[1]), os.path.basename(top[0]), str(top[1])]))
  1. service serverless.yml - 如您所见,每个函数都应包含层,您可以使用 CloudFormation 参考来引用特定层。
service: layer-test
  provider:
    name: aws
    region: ap-northeast-1
    runtime: python3.7
    stage: dev
  functions:
    exceptionExample:
      handler: handler.func
      layers:
        - ${cf:library-dev.CommonLayerExport}
      events:
        - http:
            path: exceptionExample
            method: get

handler.py - 现在我们可以轻松地从共享层导入共享模块。

import json
import Common

def func(event, context):
    try:
        1/0 # just to raise an exception and test the shared function
    except Exception as e:
        Common.printException(e)

    response = {
        "statusCode": 200,
    }
    return response

你应该注意的一件事是,由于 lambda 层不打包导入的模块,你应该导入你的层在你的服务中使用的模块。

【讨论】:

  • 您的回答似乎很有帮助,但请不要分享可能有一天会消失的链接。而是在您的答案中分享回答问题所需的信息。
  • @UnbrandManchester 感谢您的评论,我刚刚编辑了我的答案,希望对您有所帮助。
  • @msc 你介意看看stackoverflow.com/questions/63107494/… 吗?这是您回答的后续问题.. 谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-28
  • 2022-10-22
  • 2020-01-29
  • 1970-01-01
相关资源
最近更新 更多