如何正确地在无服务器的Python中共享代码?

2024-05-23 15:25:34 发布

您现在位置:Python中文网/ 问答频道 /正文

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

  • 服务1/
    • serverless.yml
    • handler.py
  • 服务2/
    • serverless.yml
    • handler.py
  • 共享
    • 模块a.py
    • 模块_b.py

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

有一个the plugin-serverless包common,它似乎可以解决这个问题,但是,它看起来不像是一种先走的方法

我感谢任何形式的帮助


Tags: 模块pip项目方法代码py服务器框架
1条回答
网友
1楼 · 发布于 2024-05-23 15:25:34
也许你可以考虑使用lambda层。您可以在这里找到快速指南:link

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

  1. library-此项目应具有以下文件结构。您在这个项目的根目录中有serverless.yml和另一个文件夹,该文件夹将作为模块导出python将被链接,并在将lambda与python一起使用时让lambda找到您的模块
./
└ 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 正如您所看到的,每个函数都应该包含层,您可以使用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

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层不打包导入的模块,所以您也应该导入您的层在您的服务中使用的模块

相关问题 更多 >