CDK v2中Lambda自定义资源导入文件遇RuntimeError问题解决
问题场景
使用Python 3.8作为Lambda运行时,通过AWS CDK v2部署自定义资源Lambda,该Lambda在每次栈部署时运行。
文件夹结构
/Dynamics/cust_resource/__init__.py /Dynamics/cust_resource/data_objects.py /Dynamics/cust_resource/lambda.py /Dynamics/cust_resource/requirements.txt /Dynamics/__init__.py /Dynamics/dyna_stack.py app.py
Lambda代码(lambda.py)
import os import boto3 import sys print('before lambda import') from data_objects import poco_data
CDK创建Lambda函数的代码
cust_res_lambda = _lambda.Function( self, 'crLambda', runtime=_lambda.Runtime.PYTHON_3_8, code=_lambda.Code.from_asset('Dynamics/cust_resource', bundling=BundlingOptions( image=_lambda.Runtime.PYTHON_3_8.bundling_image, command=["bash", "-c", "pip install -r requirements.txt -t /asset-output && cp -au . /asset-output"] )), handler='lambda.lambda_handler', function_name='crlambdaFn', )
错误日志
CloudWatch日志显示before lambda import后抛出错误:
[ERROR] RuntimeError: generator didn't stop after throw() Traceback (most recent call last): File "/var/lang/lib/python3.8/imp.py", line 234, in load_module return load_source(name, filename, file) File "/var/lang/lib/python3.8/imp.py", line 171, in load_source module = _load(spec) File "<frozen importlib._bootstrap>", line 702, in _load File "<frozen importlib._bootstrap>", line 671, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 843, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "/var/task/lambda.py", line 12, in <module> from data_objects import poco_data File "/var/task/data_objects.py", line 1, in <module> from aws_cdk import ( File "/var/task/aws_cdk/__init__.py", line 1257, in <module> from ._jsii import * File "/var/task/aws_cdk/_jsii/__init__.py", line 13, in <module> import constructs._jsii File "/var/task/constructs/__init__.py", line 43, in <module> from ._jsii import * File "/var/task/constructs/_jsii/__init__.py", line 13, in <module> __jsii_assembly__ = jsii.JSIIAssembly.load( File "/var/task/jsii/_runtime.py", line 54, in load _kernel.load(assembly.name, assembly.version, os.fspath(assembly_path)) File "/var/lang/lib/python3.8/contextlib.py", line 162, in __exit__ raise RuntimeError("generator didn't stop after throw()")
错误含义分析
这个错误的核心原因是Lambda运行环境中加载了AWS CDK相关依赖包,但CDK是用于基础设施部署的框架,其依赖的jsii运行时无法在Lambda的执行环境中正常初始化。
从调用栈可以明确看到,data_objects.py中导入了aws_cdk模块,而CDK的jsii运行时在尝试加载程序集时,依赖的内核初始化逻辑无法在Lambda环境中完成,导致上下文管理器退出时抛出“生成器未停止”的错误。
解决方案
1. 移除Lambda代码中不必要的CDK导入
检查data_objects.py,如果该文件是Lambda运行时使用的代码,完全不需要导入aws_cdk包,直接删除这一行导入语句:
# 删除此行:from aws_cdk import (...)
2. 清理requirements.txt
确保Dynamics/cust_resource/requirements.txt中不包含任何AWS CDK相关依赖(比如aws-cdk-lib、constructs等)。这些是CDK部署阶段的依赖,不需要打包到Lambda运行包中。只保留Lambda运行时真正需要的依赖(注:boto3是Lambda默认提供的,无需写入requirements.txt)。
3. 优化Bundling命令(可选)
当前的bundling命令会复制目录下所有文件到输出目录,可以添加排除规则避免冗余文件打包:
pip install -r requirements.txt -t /asset-output && cp -au . /asset-output --exclude "__pycache__" --exclude "*.pyc"
4. 验证打包内容
可以通过本地执行bundling命令测试,查看输出目录下是否还存在aws_cdk、constructs、jsii等不必要的包。如果存在,说明依赖清理不彻底,需要重新检查requirements.txt和代码中的导入语句。
内容的提问来源于stack exchange,提问作者user20358

