Skip to content

AWS Lambda 中解决 “cannot import name 'DEFAULT_CIPHERS' from 'urllib3.util.ssl_'” 错误

问题描述

在使用 AWS Lambda 执行网页抓取并保存数据到 S3 的任务时,出现以下关键错误:

json
{
  "errorMessage": "Unable to import module 'lambda_function': cannot import name 'DEFAULT_CIPHERS' from 'urllib3.util.ssl_' (/opt/python/urllib3/util/ssl_.py)",
  "errorType": "Runtime.ImportModuleError"
}

错误通常发生在以下场景:

  • AWS Lambda 运行时使用 Python 3.9
  • 使用 Lambda Layer 安装依赖(requests、pandas、beautifulsoup4)
  • 代码中导入 requests 和 boto3

核心问题原因:urllib3 2.0 版本进行了破坏性更改,删除了 DEFAULT_CIPHERS 属性。较旧版本的 boto3/botocore 尚未兼容该变更,导致模块导入失败。

解决方案

✅ 方法一:限制 urllib3 版本(推荐直接解决依赖冲突)

在依赖管理文件中明确限定 urllib3 版本小于 2.0:

txt
urllib3<2

生成 Lambda 层时使用以下命令:

shell
pip install -r requirements.txt -t ./python --no-user

注意事项

此方案兼容所有 Python 运行时版本(Python 3.6+),是问题最直接的解决方法

✅ 方法二:升级 Lambda Python 运行时(推荐长期解决方案)

更新 Lambda 配置至较新 Python 版本:

  1. AWS Lambda 控制台 → 修改函数配置
  2. 运行时设置选择:Python 3.11 或更新版本
    (如 Python 3.12)
  3. 重新部署函数

版本选择

  • Python 3.10+ 内置兼容的 urllib3 版本
  • Python 3.12 可彻底避免此类依赖冲突

✅ 方法三:更新 boto3 和 botocore(适用于需保持3.9的场景)

如果必须使用 Python 3.9,强制更新 boto3 相关库:

  1. 创建 requirements.txt
txt
boto3>=1.26.153
botocore>=1.29.153
urllib3<2
  1. 使用此文件构建 Lambda 层:
shell
pip install -r requirements.txt -t ./python --no-user

✅ 方法四:使用 Docker 构建兼容层(确保环境一致性)

创建与 Lambda 环境完全兼容的依赖层:

shell
mkdir layer
cp requirements.txt layer/requirements.txt
docker run -ti -v $(pwd)/layer:/app -w /app \
  --entrypoint /bin/bash \
  public.ecr.aws/lambda/python:3.11 \
  -c "pip3 install --target ./python -r requirements.txt"
Windows PowerShell 用户

替换 $(pwd)${pwd}

shell
docker run -ti -v ${pwd}/layer:/app -w /app ...

解决方案对比

方法适用场景优势缺点实施复杂度
urllib3<2所有版本直接解决依赖冲突需修改依赖文件
升级运行时Lambda 环境避免未来兼容问题需验证代码兼容性⭐⭐
更新 boto3需兼容旧环境解决特定核心冲突需同步多个依赖⭐⭐
Docker 构建复杂依赖项目100% 环境一致性需 Docker 环境⭐⭐⭐

根本原因解析

此错误源于库版本不匹配:

  1. urllib3 2.0+:移除了 DEFAULT_CIPHERS官方迁移说明
  2. boto3<1.26.153:依赖旧版 urllib3 接口
  3. Layer 生成环境:本地 pip 可能安装不兼容版本

:::caution Lambda 层机制 Layer 中的依赖版本会覆盖 Lambda 运行时自带库版本,因此层中不当版本会导致此类冲突 :::

最佳实践建议

  1. 明确依赖版本:始终使用 requirements.txt 固定关键库版本
  2. 使用基础设施即代码(IaC)
    python
    # 生产环境推荐版本
    boto3==1.34.112
    requests==2.32.3
    urllib3==1.26.18
  3. 定期更新运行时:每季度检查 Lambda 支持的最新 Python 版本
  4. 多阶段测试:本地、容器环境、Lambda 测试环境三级验证

如需使用 requests 特定版本,可明确指定:

txt
requests==2.28.2  # 此版本默认使用兼容的 urllib3

遵循上述方案,可彻底解决 DEFAULT_CIPHERS 导入错误,确保 Lambda 函数稳定执行网页抓取和 S3 存储操作。