python 和无服务器框架的问题
Issues with python and the serverless framework
我想了解如何在一个 serverless.yml
中设置多个 python lambda 和一个阶跃函数,每个 python lambda 都有自己的依赖项。我的所有 lambda 函数都在阶跃函数的上下文中协作,以实现共同的目标。有了这个理由,将所有代码放在一个 serverless.yml
文件中对我来说是有意义的。
作为我许多小时的反复试验和阅读的一部分,我发现 The Serverless Framework
的 serverless-python-requirements
插件有助于打包 python 依赖于 OS-specific [=] 的函数80=] 库,并且还允许分隔多个 requirements.txt
以防不同的 lambda 需要不同的依赖项。
所以此时我的问题是生成的包不包括我在 requirements.txt 中提供的依赖项,只要每个函数都有自己的 requirements.txt
这些是我的作品:
package.json
{
"engines": {
"node": ">=10.0.0",
"npm": ">=6.0.0"
},
"name": "example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"serverless-python-requirements": "^5.1.0"
},
"devDependencies": {
"serverless": "^1.72.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "ISC"
}
serverless.yml
service: example
frameworkVersion: ">=1.72.0 <2.0.0"
plugins:
- serverless-python-requirements
custom:
stage: "${opt:stage, env:SLS_STAGE, 'local'}"
log_level: "${env:LOG_LEVEL, 'INFO'}"
pythonRequirements:
dockerizePip: true
provider:
name: aws
# profile: ${self:custom.profile}
stage: ${self:custom.stage}
runtime: python3.8
environment:
LOG_LEVEL: ${self:custom.log_level}
package:
individually: true
exclude:
- ./**
include:
- vendored/**
functions:
function1:
# module: folder1
handler: folder1/function1.handler
package:
include:
- 'folder1/**'
memorySize: 128
timeout: 60
function2:
# module: folder2
handler: folder2/function2.handler
package:
include:
- 'folder2/**'
memorySize: 128
timeout: 60
最后,我的 2 个 python lambda 函数位于不同的文件夹中,其中一个需要特定的依赖项:
- 文件夹1
- function1.py
- requirements.txt
- 文件夹2
- function1.py
function1.py
import json
import logging
import os
import sys
import pyjokes
log_level = os.environ.get('LOG_LEVEL', 'INFO')
logging.root.setLevel(logging.getLevelName(log_level))
_logger = logging.getLogger(__name__)
class HandlerBaseError(Exception):
'''Base error class'''
class ComponentIdentifierBaseError(HandlerBaseError):
'''Base Component Identifier Error'''
def handler(event, context):
'''Function entry'''
_logger.debug('Event received: {}'.format(json.dumps(event)))
body = {
"message": "Go Serverless v1.0! Your function executed successfully!",
"joke":pyjokes.get_joke()
}
resp = {
'status': 'OK',
"body": json.dumps(body)
}
_logger.debug('Response: {}'.format(json.dumps(resp)))
return resp
if __name__ == "__main__":
handler('', '')
requirements.txt
pyjokes==0.6.0
function2.py
import json
import logging
import os
import sys
log_level = os.environ.get('LOG_LEVEL', 'INFO')
logging.root.setLevel(logging.getLevelName(log_level))
_logger = logging.getLogger(__name__)
class HandlerBaseError(Exception):
'''Base error class'''
class ElasticSearchPopulatorBaseError(HandlerBaseError):
'''Base Component Identifier Error'''
def handler(event, context):
'''Function entry'''
_logger.debug('Event received: {}'.format(json.dumps(event)))
resp = {
'status': 'OK'
}
_logger.debug('Response: {}'.format(json.dumps(resp)))
return resp
注意:我确实尝试在 serverless.xml
中使用 module+handler 关键字,正如在此 link 上所推荐的:ttps://github.com/UnitedIncome/serverless-python-requirements 没有任何成功
我注意到的一点是,如果我按如下方式使用模块+处理程序:
functions:
function1:
module: folder1
handler: function1.handler
package:
include:
- 'folder1/**'
memorySize: 128
timeout: 60
然后,当我在本地尝试 运行 函数时使用:serverless invoke local -f function1 --log
我收到一条错误消息:
ModuleNotFoundError: No module named 'function1'
此外,如果有人有多个具有不同 requirements.txt
的 lambda 的示例,我会非常感激,最好是与典型的 hello world 示例不同的东西,hello world 对我来说都很好用;),但在像这样的场景中,我想设置公共库,具有不同的依赖关系等,并使用一个公共的 serverless.yml 事情似乎分崩离析。同样,我的观点是这些 lambda 将在一步功能保护伞下一起运行,因此这里有很强的凝聚力,我认为它们的构建和部署应该在一个通用的无服务器服务下进行。
我最近使用 serverless-python-requirements
插件开发了一个类似的应用程序,该插件将多个 lambda 封装为一个堆栈的一部分,我在本地调用 lambda 函数时收到 ModuleNotFoundError
,但它可以远程工作;但是,当我从我的 serverless.yml
文件中删除 module
参数时,我能够在本地调用但随后它因远程执行而中断。
我已经能够通过在 serverless.yml
中设置路径前缀找到解决方法:
functions:
LambdaTest:
handler: ${env:HANDLER_PATH_PREFIX, ""}handler.handler
module: src/test_lambda
package:
include:
- src/test_lambda/**
当我在本地调用该函数时,我将环境变量添加到我的命令中:
HANDLER_PATH_PREFIX=src/test_lambda/ ./node_modules/serverless/bin/serverless.js invoke local -f LambdaTest -p ./tests/resources/base_event.yml
我在 AWS 中调用函数时没有包含环境变量。
为了让它工作,我需要添加一个 init.py 文件到我的 lambda 函数所在的根目录,代码如下(取自 this solution) 以便我包含在 lambda 目录中存在的代码中的任何模块(例如 some_module
-- 请参阅下面的目录树):
import os
import sys
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
我的 lambda 的目录结构:
src/
└── test_lambda
├── __init__.py <=== add the code to this one
├── handler.py
├── requirements.txt
└── some_module
├── __init__.py
└── example.py
关于您关于使用不同 requirements.txt
文件的 lambda 的问题——我使用 individually
参数,如下所示:
package:
individually: true
include:
- infra/**
exclude:
- "**/*"
在每个 requirements.txt
的每个 lambda 中,我使用 -r
选项引用一个单独的 requirements.txt
文件,该文件驻留在我的项目的基本目录中——这个文件包含的库对于所有 lambda 都是通用的,因此当 Serverless 为每个 lambda 安装包时,它也会包含我的 ./requirements.txt
文件中包含的包。
我已经将这个解决方案包含在一个关于 serverless-python-requirements
插件 in GitHub 的问题中,如果 module
参数的这种行为结果是一个错误。
希望对您有所帮助,如果您需要任何说明,请告诉我。
我想了解如何在一个 serverless.yml
中设置多个 python lambda 和一个阶跃函数,每个 python lambda 都有自己的依赖项。我的所有 lambda 函数都在阶跃函数的上下文中协作,以实现共同的目标。有了这个理由,将所有代码放在一个 serverless.yml
文件中对我来说是有意义的。
作为我许多小时的反复试验和阅读的一部分,我发现 The Serverless Framework
的 serverless-python-requirements
插件有助于打包 python 依赖于 OS-specific [=] 的函数80=] 库,并且还允许分隔多个 requirements.txt
以防不同的 lambda 需要不同的依赖项。
所以此时我的问题是生成的包不包括我在 requirements.txt 中提供的依赖项,只要每个函数都有自己的 requirements.txt
这些是我的作品:
package.json
{
"engines": {
"node": ">=10.0.0",
"npm": ">=6.0.0"
},
"name": "example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"serverless-python-requirements": "^5.1.0"
},
"devDependencies": {
"serverless": "^1.72.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "ISC"
}
serverless.yml
service: example
frameworkVersion: ">=1.72.0 <2.0.0"
plugins:
- serverless-python-requirements
custom:
stage: "${opt:stage, env:SLS_STAGE, 'local'}"
log_level: "${env:LOG_LEVEL, 'INFO'}"
pythonRequirements:
dockerizePip: true
provider:
name: aws
# profile: ${self:custom.profile}
stage: ${self:custom.stage}
runtime: python3.8
environment:
LOG_LEVEL: ${self:custom.log_level}
package:
individually: true
exclude:
- ./**
include:
- vendored/**
functions:
function1:
# module: folder1
handler: folder1/function1.handler
package:
include:
- 'folder1/**'
memorySize: 128
timeout: 60
function2:
# module: folder2
handler: folder2/function2.handler
package:
include:
- 'folder2/**'
memorySize: 128
timeout: 60
最后,我的 2 个 python lambda 函数位于不同的文件夹中,其中一个需要特定的依赖项:
- 文件夹1
- function1.py
- requirements.txt
- 文件夹2
- function1.py
function1.py
import json
import logging
import os
import sys
import pyjokes
log_level = os.environ.get('LOG_LEVEL', 'INFO')
logging.root.setLevel(logging.getLevelName(log_level))
_logger = logging.getLogger(__name__)
class HandlerBaseError(Exception):
'''Base error class'''
class ComponentIdentifierBaseError(HandlerBaseError):
'''Base Component Identifier Error'''
def handler(event, context):
'''Function entry'''
_logger.debug('Event received: {}'.format(json.dumps(event)))
body = {
"message": "Go Serverless v1.0! Your function executed successfully!",
"joke":pyjokes.get_joke()
}
resp = {
'status': 'OK',
"body": json.dumps(body)
}
_logger.debug('Response: {}'.format(json.dumps(resp)))
return resp
if __name__ == "__main__":
handler('', '')
requirements.txt
pyjokes==0.6.0
function2.py
import json
import logging
import os
import sys
log_level = os.environ.get('LOG_LEVEL', 'INFO')
logging.root.setLevel(logging.getLevelName(log_level))
_logger = logging.getLogger(__name__)
class HandlerBaseError(Exception):
'''Base error class'''
class ElasticSearchPopulatorBaseError(HandlerBaseError):
'''Base Component Identifier Error'''
def handler(event, context):
'''Function entry'''
_logger.debug('Event received: {}'.format(json.dumps(event)))
resp = {
'status': 'OK'
}
_logger.debug('Response: {}'.format(json.dumps(resp)))
return resp
注意:我确实尝试在 serverless.xml
中使用 module+handler 关键字,正如在此 link 上所推荐的:ttps://github.com/UnitedIncome/serverless-python-requirements 没有任何成功
我注意到的一点是,如果我按如下方式使用模块+处理程序:
functions:
function1:
module: folder1
handler: function1.handler
package:
include:
- 'folder1/**'
memorySize: 128
timeout: 60
然后,当我在本地尝试 运行 函数时使用:serverless invoke local -f function1 --log
我收到一条错误消息:
ModuleNotFoundError: No module named 'function1'
此外,如果有人有多个具有不同 requirements.txt
的 lambda 的示例,我会非常感激,最好是与典型的 hello world 示例不同的东西,hello world 对我来说都很好用;),但在像这样的场景中,我想设置公共库,具有不同的依赖关系等,并使用一个公共的 serverless.yml 事情似乎分崩离析。同样,我的观点是这些 lambda 将在一步功能保护伞下一起运行,因此这里有很强的凝聚力,我认为它们的构建和部署应该在一个通用的无服务器服务下进行。
我最近使用 serverless-python-requirements
插件开发了一个类似的应用程序,该插件将多个 lambda 封装为一个堆栈的一部分,我在本地调用 lambda 函数时收到 ModuleNotFoundError
,但它可以远程工作;但是,当我从我的 serverless.yml
文件中删除 module
参数时,我能够在本地调用但随后它因远程执行而中断。
我已经能够通过在 serverless.yml
中设置路径前缀找到解决方法:
functions:
LambdaTest:
handler: ${env:HANDLER_PATH_PREFIX, ""}handler.handler
module: src/test_lambda
package:
include:
- src/test_lambda/**
当我在本地调用该函数时,我将环境变量添加到我的命令中:
HANDLER_PATH_PREFIX=src/test_lambda/ ./node_modules/serverless/bin/serverless.js invoke local -f LambdaTest -p ./tests/resources/base_event.yml
我在 AWS 中调用函数时没有包含环境变量。
为了让它工作,我需要添加一个 init.py 文件到我的 lambda 函数所在的根目录,代码如下(取自 this solution) 以便我包含在 lambda 目录中存在的代码中的任何模块(例如 some_module
-- 请参阅下面的目录树):
import os
import sys
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
我的 lambda 的目录结构:
src/
└── test_lambda
├── __init__.py <=== add the code to this one
├── handler.py
├── requirements.txt
└── some_module
├── __init__.py
└── example.py
关于您关于使用不同 requirements.txt
文件的 lambda 的问题——我使用 individually
参数,如下所示:
package:
individually: true
include:
- infra/**
exclude:
- "**/*"
在每个 requirements.txt
的每个 lambda 中,我使用 -r
选项引用一个单独的 requirements.txt
文件,该文件驻留在我的项目的基本目录中——这个文件包含的库对于所有 lambda 都是通用的,因此当 Serverless 为每个 lambda 安装包时,它也会包含我的 ./requirements.txt
文件中包含的包。
我已经将这个解决方案包含在一个关于 serverless-python-requirements
插件 in GitHub 的问题中,如果 module
参数的这种行为结果是一个错误。
希望对您有所帮助,如果您需要任何说明,请告诉我。