CentOS 7 编译安装 Python 3.9 解决 SSL 模块缺失问题

在 CentOS 7 上从源码编译 Python 3.9 时,经常遇到 SSL 模块无法导入的问题,导致 pip 无法使用 HTTPS 源,甚至影响 Ansible 等工具的正常运行。本文汇总了常见错误信息,分析了根本原因,并提供了一套经过验证的完整解决方案,最终给出可直接使用的安装脚本。

1. 报错信息汇总

1.1 编译后无法导入 ssl 模块

复制代码
  >>> import ssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/ssl.py", line 98, in <module>
    import _ssl
ModuleNotFoundError: No module named '_ssl'

1.2 pip 操作提示 SSL 不可用

复制代码
  WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available."))

1.3 Ansible 执行时因 SSL 问题失败

复制代码
  fatal: [192.168.233.128]: FAILED! => {"changed": false, "msg": "SSL validation is not available in your version of python. You can use validate_certs=False, however this is unsafe and not recommended"}

1.4 其他常见依赖缺失

  • zipimport.ZipImportError: can't decompress data; zlib not available
  • • 编译时提示找不到 OpenSSL 头文件或库

2. 问题原因分析

  • Python 3.9 要求 OpenSSL 1.1.1 或更高版本 ,而 CentOS 7 系统默认的 OpenSSL 版本为 1.0.2,且系统自带的 openssl-devel 包仅提供 1.0.2 的头文件和库。
  • • 即使通过 EPEL 安装了 openssl11-devel,由于系统默认的编译环境和链接器仍会优先查找 /usr/include/usr/lib64 下的旧版本,导致 Python 的 configure 脚本找不到正确的 OpenSSL 1.1.1,或者找到的是不兼容的旧版本,最终无法编译出 _ssl 模块。
  • • 简单指定 --with-openssl=/usr/include/openssl11 并不足够,因为该目录下没有完整的库文件结构(缺少 lib 子目录),且运行时链接可能依然指向旧库。

3. 解决方案

核心思路 :安装 OpenSSL 1.1.1 开发包,并通过 pkg-config 获取正确的编译和链接标志,将其传递给 Python 的构建系统。

3.1 安装 OpenSSL 1.1.1 开发包

CentOS 7 可以通过 EPEL 仓库安装 openssl11-devel,该包会提供 OpenSSL 1.1.1 的头文件、库文件以及 pkg-config 配置文件(openssl11.pc)。

复制代码
  sudo yum install -y epel-release
sudo yum install -y openssl11 openssl11-devel

3.2 使用 pkg-config 设置编译环境变量

在运行 Python 的 ./configure 脚本之前,导出 CFLAGSLDFLAGS 环境变量,让编译器和链接器知道去哪里找 OpenSSL 1.1.1 的头文件和库。

复制代码
  export CFLAGS="$CFLAGS $(pkg-config --cflags openssl11)"
export LDFLAGS="$LDFLAGS $(pkg-config --libs openssl11)"

pkg-config --cflags openssl11 会输出类似 -I/usr/include/openssl11 的选项,而 --libs 会输出 -L/usr/lib64/openssl11 -lssl -lcrypto 等。这样 Python 的构建系统就能正确找到 OpenSSL 1.1.1。

3.3 配置并编译 Python

执行配置时不需要 再使用 --with-openssl 参数,因为环境变量已经指定了路径。

复制代码
  ./configure --enable-optimizations --prefix=/usr/local/python3.9
make -j$(nproc)
sudo make altinstall

3.4 验证 SSL 模块

安装完成后,验证 SSL 模块是否可用:

复制代码
  /usr/local/python3.9/bin/python3.9 -c "import ssl; print(ssl.OPENSSL_VERSION)"

如果输出 OpenSSL 1.1.1 的版本号,则成功。

4. 完整版安装脚本

以下脚本整合了所有步骤,可直接复制粘贴到 CentOS 7 系统中执行(以 root 用户或使用 sudo)。

复制代码
  #!/bin/bash
# CentOS 7 编译安装 Python 3.9 并启用 SSL 模块

set -e  # 遇到错误立即退出

# 1. 安装系统依赖和 OpenSSL 1.1.1
yum install -y epel-release
yum groupinstall -y "Development Tools"
yum install -y openssl11 openssl11-devel \
    zlib-devel bzip2-devel ncurses-devel sqlite-devel \
    readline-devel tk-devel libffi-devel expat-devel gdbm-devel

# 2. 下载 Python 3.9 源码
cd /opt
wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tar.xz
tar -xf Python-3.9.0.tar.xz
cd Python-3.9.0

# 3. 设置环境变量,使编译器和链接器能找到 OpenSSL 1.1.1
export CFLAGS="$CFLAGS $(pkg-config --cflags openssl11)"
export LDFLAGS="$LDFLAGS $(pkg-config --libs openssl11)"

# 4. 配置、编译、安装
./configure --enable-optimizations --prefix=/usr/local/python3.9
make -j$(nproc)
make altinstall

# 5. 创建符号链接(可选)
ln -s /usr/local/python3.9/bin/python3.9 /usr/local/bin/python3.9
ln -s /usr/local/python3.9/bin/pip3.9 /usr/local/bin/pip3.9

# 6. 验证 SSL 模块
/usr/local/python3.9/bin/python3.9 -c "import ssl; print(ssl.OPENSSL_VERSION)"

echo "Python 3.9 installation completed successfully."

5. 验证与测试

5.1 测试 SSL 导入

复制代码
  python3.9 -c "import ssl; print('SSL module is available')"

5.2 测试 pip 使用 HTTPS 源

复制代码
  pip3.9 install --upgrade pip

应不再出现 SSL 相关警告。

5.3 测试 Ansible 远程执行

在 Ansible 控制节点上,确保 inventory 中指定了解释器路径:

复制代码
  [target]
192.168.233.128 ansible_python_interpreter=/usr/local/python3.9/bin/python3.9

然后执行涉及 HTTPS 下载的任务,应不再报 SSL 验证错误。

6. 常见问题及注意事项

6.1 为什么不用 --with-openssl

在 Python 3.9 中,--with-openssl 只能指定一个根目录(如 /usr/local/openssl),要求该目录下有 include/lib/ 子目录。而通过 EPEL 安装的 openssl11-devel 将头文件放在了 /usr/include/openssl11,库文件在 /usr/lib64/openssl11,不符合标准结构。使用 pkg-config 传递标志是更灵活且通用的做法。

6.2 如果 pkg-config 找不到 openssl11

请确保 openssl11-devel 已正确安装,其生成的 .pc 文件通常位于 /usr/lib64/pkgconfig/openssl11.pc。如果 pkg-config 仍找不到,可以设置 PKG_CONFIG_PATH 环境变量:

复制代码
  export PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$PKG_CONFIG_PATH

6.3 关于 zlib 模块缺失

如果同时遇到 zlib 模块缺失,请确保已安装 zlib-devel,并在编译前导出 CFLAGSLDFLAGS 中包含 zlib 的相关路径(通常系统默认路径已包含,无需额外指定)。

6.4 使用 altinstall 避免冲突

始终使用 make altinstall 而不是 make install,以防止覆盖系统自带的 Python 2 或 Python 3 可执行文件,避免破坏系统工具(如 yum)。

6.5 虚拟环境建议

即使编译成功,也建议为项目创建虚拟环境,避免使用 root 权限安装包,并隔离依赖。

结语

通过上述方法,可以在 CentOS 7 上成功编译出带有完整 SSL 支持的 Python 3.9,彻底解决 _ssl 模块缺失的问题。本文提供的脚本已在 CentOS 7.9 上验证通过,可放心使用。如果在实践中遇到其他问题,欢迎反馈交流。

相关推荐
python猿1 小时前
打卡Python王者归来--第29天
python
幸福清风2 小时前
【Python】运维效率翻倍|批处理日志分割升级Python GUI,一键打包exe无乱码,零基础也能用
python·打包·日志分割
宵时待雨2 小时前
C++笔记归纳13:map & set
开发语言·数据结构·c++·笔记·算法
xiangpanf2 小时前
PHP与Vue:前后端技术深度对比
开发语言·vue.js·php
小狗丹尼4003 小时前
JSON 基础认知、数据转换与 Flask 前后端交互全解
python·flask·json
1104.北光c°3 小时前
滑动窗口HotKey探测机制:让你的缓存TTL更智能
java·开发语言·笔记·程序人生·算法·滑动窗口·hotkey
for_ever_love__4 小时前
Objective-C学习 NSSet 和 NSMutableSet 功能详解
开发语言·学习·ios·objective-c
zm-v-159304339865 小时前
Python 数据挖掘从入门到精通:回归 / 分类 / 聚类 / 关联分析完整教程
python·数据挖掘·回归
似水明俊德10 小时前
02-C#.Net-反射-面试题
开发语言·面试·职场和发展·c#·.net