Python Lambda运行时:配置与依赖管理
说起 Lambda 的运行时配置,我记得刚开始做第一个自动化巡检函数时,纠结了好久该用哪个 Python 版本。其实 AWS 支持 Python 3.8、3.9、3.10、3.11 甚至 3.12,但好多项目还在用 3.8。我个人习惯是——如果没有历史包袱,直接上最新稳定版。为什么?因为 Lambda 的底层运行环境会定期更新,老版本迟早退役,到时候你得迁一次,不如一开始就用新的。
运行时版本选择
目前主流的 Lambda Python 运行时版本对比如下:
| 运行时标识 | Python 版本 | 底层 OS | 建议场景 |
|---|---|---|---|
python3.9 | 3.9 | Amazon Linux 2 | 多数新项目推荐 |
python3.10 | 3.10 | Amazon Linux 2 | 需要 match 语句等新特性 |
python3.11 | 3.11 | Amazon Linux 2023 | 性能最优,推荐长期项目 |
python3.12 | 3.12 | Amazon Linux 2023 | 最新,但少数第三方库可能不兼容 |
python3.11。它兼顾了性能和生态兼容性。我在项目里从 3.8 迁到 3.11 后,冷启动快了大约 300ms。
依赖管理:三种主流方式
Lambda 不是一台完整的服务器,你不能直接 pip install 然后跑。你需要把依赖包和代码一起打包,或者用 Lambda Layer 共享。说白了,就是让你的 Python 代码在云端能找到那些第三方库。
方式一:直接打包进 ZIP
最原始的方式。把 requirements.txt 里列出的库用 pip 装到一个目录,然后和函数代码一起压缩。
步骤:
- 创建函数目录,比如
my-function/ - 编写
requirements.txt,例如:boto3==1.28.0 requests==2.31.0 pytz==2023.3 - 在本机运行:
pip install -r requirements.txt -t my-function/ cd my-function/ zip -r ../function.zip . - 上传
function.zip到 Lambda
__pycache__ 和 .pyc 文件,否则上传后可能因为缓存冲突导致函数失败。我习惯在 .gitignore 里加上 *.pyc,打包前用 find . -name '*.pyc' -delete 清理一遍。
方式二:Lambda Layer(推荐)
如果你有多个函数共享同一套依赖,用 Layer 最省事。Layer 本质上也是一个 ZIP 包,但需要按特定目录结构存放:
python/lib/python3.x/site-packages/—— 放第三方库python/lib/—— 可选,放自定义模块
我一般这样创建:
mkdir -p layer/python/lib/python3.11/site-packages
pip install requests -t layer/python/lib/python3.11/site-packages
cd layer
zip -r layer.zip python
然后在 AWS 控制台或 CLI 中创建 Layer,再附加给函数。一次创建,所有函数都能用。更新依赖时只需要新 Layer,函数代码不用改。
方式三:容器镜像 (ECR)
当你的依赖特别重,比如用了 Pandas、OpenCV、Pillow 等大型库,或者需要自定义 C 扩展库时,直接打包 ZIP 可能超限,Layer 也顶不住。这时 Lambda 支持用容器镜像部署。
你需要:
- 写一个
Dockerfile,继承官方的 Lambda Python 基础镜像:FROM public.ecr.aws/lambda/python:3.11 COPY requirements.txt . RUN pip install -r requirements.txt COPY app.py . CMD ["app.lambda_handler"] - 构建镜像并推送到 ECR:
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <account-id>.dkr.ecr.us-east-1.amazonaws.com docker build -t my-log-check . docker tag my-log-check:latest <repo-uri>:latest docker push <repo-uri>:latest - 创建 Lambda 函数时,选择「容器镜像」并填写镜像 URI
注意,镜像最多 10GB。启动时间会比 ZIP 长一点,但胜在灵活。我个人在日志巡检中只用过一次镜像,因为那个函数需要调用 OCR 库,依赖实在太大。
依赖管理决策流程图
下面这张图梳理了三种方式的选择逻辑,你写自动化巡检脚本时可以直接套用:
环境变量与密钥管理
日志巡检要用到 CloudWatch 日志组、S3 存储桶、可能还有外部 。千万别在代码里写死。Lambda 提供了环境变量,直接在控制台设置即可。
我的习惯:敏感信息(比如 Webhook )用 AWS Secrets Manager 或 Systems Manager Parameter Store,Lambda 函数运行时通过 SDK 读取。不要在环境变量里存明文密码。
示例代码(读取 Parameter Store):
import boto3
ssm = boto3.client('ssm')
def get_config(key):
resp = ssm.get_parameter(Name=key, WithDecryption=True)
return resp['Parameter']['Value']
# 使用
slack_url = get_config('/log-monitor/slack-webhook')
- 运行时版本选
python3.11稳中求快 - 依赖优先考虑 Layer,超过 250MB 用容器镜像
- 打包时注意清理缓存文件,避免莫名其妙报错
- 密钥走 Parameter Store,别硬编码
避坑指南
我最后再列几个实际中容易翻车的地方:
- 本地环境与 Lambda 环境不一致:你本机用 macOS,pip 装的可能是
macosx_*的 wheel,上传到 Amazon Linux 上就报错。一定要用pip install --platform manylinux2014_x86_64 --only-binary=:all:来限制平台。或者老老实实去 EC2 或 CodeBuild 上打包。 - Layer 解压路径弄错:我曾经把第三方库放在了
python/lib/python3.9/site-packages/下面,但函数运行时版本是 3.11,死活找不到库。检查一下 Layer 的目录结构,版本号要对上。 - 容器镜像冷启动慢:如果你用容器镜像做日志巡检,冷的请求可能多等 2~3 秒。可以用 Provisioned Concurrency 预先热好,但会多花钱。权衡一下。
- ZIP 包超过 50MB?:Lambda 的控制台直接上传 ZIP 有限制 50MB,超过就要放 S3 然后通过 URL 上传。
嗯,以上就是关于 Lambda 运行时配置与依赖管理的主要干货。你写自动化巡检脚本时,把这部分的规格定好,后面其他章节的代码就能顺畅跑起来。到底用 ZIP、Layer 还是镜像,根据你的依赖规模和多函数复用程度决定就好。