为什么Ubuntu上的Python 3.8提示No module named '_ssl'

Ada
Ada
发布时间:2026-10-31 | 8人浏览过
原创

深入解析在Ubuntu系统上运行或编译Python 3.8时出现No module named '_ssl'的根本原因,涵盖缺少libssl-dev开发库与Ubuntu 22.04+下OpenSSL 3.0 API断代两大核心场景,并提供详实的排查命令与完整可落地的解决方案。

技术排查与实战修复
在 Ubuntu 环境下运行或构建 Python 3.8 时遇到 No module named '_ssl' 报错,核心原因是 Python 标准库底层的 C 扩展模块 _ssl.so 缺失或未成功构建。该扩展模块强依赖操作系统的 OpenSSL 开发头文件与动态库。绝大多数情况下,该问题源于两类具体场景:一是在通过源码编译或 pyenv 安装 Python 3.8 前,系统未预装 libssl-dev 开发依赖;二是在 Ubuntu 22.04 及以上较新的系统环境中,默认集成的 OpenSSL 3.0 与 Python 3.8 早期版本的源码构建逻辑发生 API 兼容性冲突,导致编译阶段静默放弃了 _ssl 扩展模块的生成。
为什么Ubuntu上的Python 3.8提示No module named '_ssl'
图 0:Ubuntu 环境下 Python 3.8 的 _ssl 模块断裂成因概览

一、故障表现与关键排查点

在 Ubuntu 上,该错误通常并不发生在基础语法的执行期间,而是在脚本或命令行尝试建立安全网络连接时突然暴露。最典型的高频触发点是在新安装的 Python 3.8 环境中使用 pip 安装第三方包,或者执行网络请求脚本:

python3.8 -m pip install requests
典型终端报错输出
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/local/lib/python3.8/urllib/request.py", line 2589, in <module>
    import ssl
  File "/usr/local/lib/python3.8/ssl.py", line 98, in <module>
    import _ssl #<-- 抛出核心异常
ModuleNotFoundError: No module named '_ssl'

这一报错具有迷惑性。很多使用者会误以为是 ssl 库需要通过 pip install ssl 进行单独安装,但尝试安装后会发现 pip 自身正是因为缺少 SSL 支持而完全无法连接 PyPI 服务器。

要理解这个错误,必须厘清 Python 标准库中 ssl 的实现架构:Python 的 ssl.py 只是一个上层的纯 Python 包装器,它内部所有加解密、证书校验与 TLS 握手操作,全部委托给底层的 C 语言扩展模块 _ssl。在 Linux 系统中,这个底层模块编译后的物理实体是名为 _ssl.cpython-38-x86_64-linux-gnu.so 的共享库文件,通常存放于 Python 安装路径的 lib-dynload/ 目录下。

# 检查当前 Python 3.8 的 lib-dynload 目录
ls -l /usr/local/lib/python3.8/lib-dynload/ | grep _ssl

如果执行该命令没有任何输出,说明 Python 在构建安装时根本没有生成 _ssl.so。此时 ssl.py 执行 import _ssl 时自然会触发 ModuleNotFoundError。

为什么Ubuntu上的Python 3.8提示No module named '_ssl'
图 1:Python 标准库 ssl 与系统底层 OpenSSL 的依赖关系及故障缺失节点

二、深层原因剖析:为什么缺少 _ssl.so

在 Ubuntu 上,官方软件源对每个发行版提供有默认的 Python 版本(例如 Ubuntu 20.04 默认为 Python 3.8.10)。通过官方源直接执行 sudo apt install python3 安装的 Python,其 _ssl 扩展模块是完备的。

出现 No module named '_ssl' 的机器,绝大多数属于以下情况之一:开发者自行下载源码包执行了 ./configure && make,或者通过 pyenv install 3.8.x、自定义 Docker 镜像构建脚本进行编译安装。导致 _ssl.so 缺失的具体原因有二:

原因一:CPython 源码编译机制的“容错陷阱”

当我们在 Linux 终端中运行 Python 源码的 ./configure 与 make 时,CPython 的构建体系(基于 Makefile 与 setup.py)将模块划分为“核心内置模块”与“可选扩展模块”。

_ssl 属于可选扩展模块。如果在编译开始之前,系统中没有安装 OpenSSL 的 C 语言头文件(openssl/ssl.h 等),Python 的构建脚本不会直接报错中断编译。相反,它会认为当前主机不需要或无法构建该特性,静默跳过 Modules/_ssl.c 的编译,仅在整个 make 流程的最末尾打印几行容易被滚屏忽略的提示信息:

make 阶段末尾的关键警告提示
Python build finished successfully and the input extension modules were built.
The necessary bits to build these optional modules were not found:
_ssl                  _hashlib              _tkinter
To find the necessary bits, look in setup.py in detect_modules() for the module's name.

随后执行 sudo make install 或 sudo make altinstall 时,安装程序依然会报告成功,并把没有 _ssl.so 的 Python 3.8 二进制文件完整写入系统路径。直到后续用户运行涉及 HTTPS 的代码,问题才彻底暴露。

原因二:Ubuntu 22.04+ 与 OpenSSL 3.0 的 API 兼容性断代

这是近年来在 Ubuntu 22.04 LTS (Jammy Jellyfish) 或 Ubuntu 24.04 LTS 上编译 Python 3.8 时最隐蔽、最普遍遇到的硬性阻塞。

Python 3.8 于 2019 年 10 月发布,其生命周期主要锚定在 OpenSSL 1.1.1 与 1.0.2 版本。而 Ubuntu 22.04 LTS 首次将系统全局默认的 OpenSSL 升级到了 OpenSSL 3.0 系列。OpenSSL 3.0 进行了大幅度重构,废弃了大量旧版宏定义、上下文操作函数以及不透明结构体直访机制。

因此,即便在 Ubuntu 22.04 上执行了 sudo apt install libssl-dev,安装的也是 OpenSSL 3.0 的开发库。当 Python 3.8(尤其是 3.8.0 至 3.8.12 等老版本)的 Modules/_ssl.c 尝试引入这些新头文件时,GCC 编译器会因函数原型不兼容、类型未定义等错误直接编译失败。构建系统检测到编译报错后,再次触发“容错机制”,将 _ssl 标记为构建失败并默默跳过。

为什么Ubuntu上的Python 3.8提示No module named '_ssl'
图 2:Ubuntu 不同版本下的 OpenSSL 分布及对应的排查分支

三、精准修复方案与完整操作步骤

在修复前,先运行以下命令确认系统当前的 Ubuntu 发行版和默认 OpenSSL 版本号:

lsb_release -a
openssl version

根据输出结果,选用对应的解决方案。

方案 A:针对 Ubuntu 20.04 及更早版本(标准依赖补全)

如果系统返回的是 Ubuntu 20.04 或 18.04,说明系统内核提供的就是兼容的 OpenSSL 1.1.1。此时只需要安装全套编译构建依赖,然后重新配置编译即可:

# 1. 更新源并安装必需的编译依赖与 OpenSSL 头文件
sudo apt update
sudo apt install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev     libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev wget libbz2-dev

# 2. 进入 Python 3.8 源码根目录
cd Python-3.8.18  # 以实际解压目录为准

# 3. 清理之前的错误构建缓存
make distclean

# 4. 重新执行配置,推荐开启优化选项
./configure --enable-optimizations

# 5. 编译并使用 altinstall 安装(切勿直接 make install 以免覆盖系统默认 python)
make -j$(nproc)
sudo make altinstall

方案 B:针对 Ubuntu 22.04 及更高版本(独立编译 OpenSSL 1.1.1)

如果系统是 Ubuntu 22.04 或 24.04,直接使用 apt install libssl-dev 得到的将是 OpenSSL 3.0,无法解决 Python 3.8 的编译问题。

⚠️ 严正警告

绝对不要尝试降级或替换 Ubuntu 系统自带的 /usr/bin/openssl 和系统 libssl.so.3!Ubuntu 22.04+ 的包管理器 apt、系统核心服务 systemd 以及远程管理 ssh 均紧密绑定 OpenSSL 3.0。破坏全局 OpenSSL 会直接导致服务器无法联网、甚至重启后 SSH 服务崩溃断连。

正确的做法是:将 OpenSSL 1.1.1 源码下载并编译安装到独立的隔离路径(例如 /usr/local/openssl11),然后在编译 Python 3.8 时通过参数明确指定该独立路径。具体执行步骤如下:

# 第一步:准备基础编译工具链
sudo apt update
sudo apt install -y build-essential zlib1g-dev libffi-dev libsqlite3-dev wget

# 第二步:下载并编译 OpenSSL 1.1.1 到独立目录
cd /usr/local/src
sudo wget https://www.openssl.org/source/old/1.1.1/openssl-1.1.1w.tar.gz
sudo tar -zxvf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w

# 配置安装前缀为 /usr/local/openssl11,启用动态链接库生成
sudo ./config --prefix=/usr/local/openssl11 --openssldir=/usr/local/openssl11 shared zlib
sudo make -j$(nproc)
sudo make install

# 第三步:确保动态链接器能够加载该独立库(配置软链接或 ld.so.conf)
echo "/usr/local/openssl11/lib" | sudo tee /etc/ld.so.conf.d/openssl11.conf
sudo ldconfig

# 第四步:进入 Python 3.8 源码目录,指定 OpenSSL 独立路径
cd /path/to/Python-3.8.18
make distclean

./configure     --enable-optimizations     --with-openssl=/usr/local/openssl11     --with-openssl-rpath=auto

# 第五步:多核编译与安装
make -j$(nproc)
sudo make altinstall
为什么Ubuntu上的Python 3.8提示No module named '_ssl'
图 3:针对 Ubuntu 22.04+ 系统实施 OpenSSL 1.1.1 隔离与 Python 3.8 编译全流程

补充场景:通过 pyenv 管理 Python 3.8

如果你是使用 pyenv 安装 Python 3.8,在 Ubuntu 22.04+ 上直接执行 pyenv install 3.8.18 同样会遭遇该错误。解决机制完全一致,需要在执行安装命令前,通过环境变量把编译选项与上面编译好的 OpenSSL 1.1.1 目录链接起来:

# 为 pyenv 显式指定 OpenSSL 1.1.1 路径
CFLAGS="-I/usr/local/openssl11/include" LDFLAGS="-L/usr/local/openssl11/lib" pyenv install 3.8.18

四、验证修复成果与长效防坑清单

编译安装完成后,必须立即通过以下两项核心验证,确保 _ssl 扩展模块已被正确装载,且底层能够识别正确的 OpenSSL 库版本:

# 1. 验证 Python 3.8 是否能正常导入 ssl 并打印底层版本
python3.8 -c "import ssl; print(ssl.OPENSSL_VERSION)"

# 2. 验证 pip 的 HTTPS 通信能力
python3.8 -m pip --version
验证通过的预期终端输出
OpenSSL 1.1.1w 11 Sep 2023
pip 23.3.1 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)

当控制台能准确打印出 OpenSSL 1.1.1x 并且 pip 能够正常响应时,表明底层 C 扩展模块已完美对接,No module named '_ssl' 彻底解决。

为什么Ubuntu上的Python 3.8提示No module named '_ssl'
图 4:Python 3.8 SSL 故障排查、版本处置与生产环境防坑自检体系

总结与维护建议

在 Linux 系统的实际开发与运维中,Python 解释器与操作系统底层 C 库(如 OpenSSL、SQLite、FFI)存在强耦合关系。当遇到 No module named '_ssl' 时:

  • 先查 Ubuntu 版本与 OpenSSL 基准:搞清楚是纯粹的缺少开发头文件,还是新旧版本 API 冲突;
  • 区分系统软件源安装与源码自编:系统源安装的 Python 几乎不会遗漏该模块,自编或 pyenv 安装是重灾区;
  • 严格遵守隔离原则:在 Ubuntu 22.04+ 等新系统上运行 Python 3.8 这类旧版本时,务必将 OpenSSL 1.1.1 约束在独立目录,使用 --with-openssl 静态或 rpath 链接,既满足旧 Python 的编译要求,又确保整个操作系统的核心网络组件稳定安全。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表