ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

CentOS源码编译安装Python 3.10完整指南与避坑实践

CentOS源码编译安装Python 3.10完整指南与避坑实践 1. 项目概述与安装方案选型1.1 为什么要自己动手装 Python 3.10只要你是做运维或后端开发的大概率会遇到这个场景新项目用了 Python 3.10 的新语法代码在本地跑得好好的一上服务器就报错。一查CentOS 7 自带的还是 Python 2.7.5CentOS 8 带的是 3.6CentOS 9 是 3.9离 3.10 都差着版本。更麻烦的是系统的 yum 包管理器底层依赖的是旧版 Python你不能直接“升级”系统自带的 Python否则 yum 立刻罢工。这时候最稳妥的办法就是在 CentOS 上单独编译安装一套 Python 3.10放在独立的目录里跟系统 Python 完全隔离。装完之后你可以在命令行敲python3.10使用新版也可以给项目单独建一个虚拟环境互不干扰。整个过程并不复杂但坑不少依赖库缺一个pip 可能装上就废openssl 版本不够ssl 模块直接不可用configure 参数选错编译的时间能翻好几倍。这篇文章我就把完整流程拆开讲清楚从方案选型、依赖准备、编译参数到常见问题排查全部按我实际在服务器上操作的顺序来写。适合刚接触 Linux 的后端开发也适合要批量部署环境的运维同学。照着我这个走一遍基本十分钟能编译上后面踩坑点我也都给你标出来了。1.2 四种安装方式到底选哪个先说结论服务器环境最推荐“源码编译安装”没有之一。但我也把其他方式列出来方便你根据场景自己判断。安装方式适用场景优点缺点yum / EPEL 源安装对版本要求不严格命令少、速度快EPEL 仓库往往没有 Python 3.10有也是 3.6/3.8 级别版本不可控SCLSoftware CollectionsCentOS 7 老环境应急不覆盖系统 Python部分 SCL 源已停止维护配置源比较折腾源码编译生产服务器、版本敏感项目版本精确、目录隔离、可定制性强编译耗时长依赖库要手动补齐pyenv开发机多版本切换版本切换方便、用户级安装生产环境多一层管理工具增加了复杂度实际上你如果去查 CentOS 官方源Python 3.10 基本是找不到的。CentOS 7 的生命周期已经结束官方源里 Python 还是老版本CentOS Stream 9 自带 3.9但很多业务偏偏要 3.10 的特性比如match语句、更清晰的类型报错、性能优化等只能走源码编译这条路。源码编译看起来麻烦但你只要把依赖装全后面的坑就少一大半。1.3 整体思路避免“污染”系统 Python整个安装过程可以拆成四步装依赖、下源码、编译安装、配置环境。这里面最核心的一条原则是绝对不要用 make install 直接覆盖系统路径下的python或python3命令因为 CentOS 的 yum、firewalld、selinux 等一堆系统工具都依赖旧版 Python。我用的是make altinstall这个名字里有 “alt” 就是告诉你它只会生成python3.10这样的独立命令不动系统原来的 Python。目录规划上我把 Python 3.10 装到/usr/local/python3.10这样卸载也方便删一个目录就干净了。后面所有项目的虚拟环境也都基于这个路径创建跟系统环境完全隔离出问题也不影响其他服务。这就是整个方案的核心思路。2. 安装前准备依赖与源码获取2.1 基础编译工具链一次装齐源码编译第一步先把编译器和依赖库装好。我习惯这样一把梭yum -y groupinstall Development Tools yum -y install wget tar zlib-devel bzip2-devel openssl-devel libffi-devel \ readline-devel sqlite-devel ncurses-devel gdbm-devel tk-devel xz-devel第一行是安装 gcc、make、patch 这一整套编译工具。如果你用的 CentOS 是最小化安装这一步尤其重要别跳。第二行的每个包都不是随便装的少了哪一个后面编译出来的 Python 就缺对应的功能模块。比如zlib-devel缺失pip装包时一解压就报错libffi-devel缺失ctypes模块直接编译失败而很多第三方库都依赖 ctypes。这里提醒一句Development Tools这个组包比较大下载大概几百 MB耗时要几分钟属于正常现象。如果服务器网络比较慢可以先把 yum 源换成国内镜像比如清华源或阿里源速度能快不少。换源的方法很简单修改/etc/yum.repos.d/CentOS-Base.repo里的 baseurl 就行这里不展开你网上搜“centos 换国内源”就有现成配置。2.2 这几个关键库提前解释一下用途很多人装完 Python发现pip install的时候报一个很诡异的错ModuleNotFoundError: No module named _ssl。问题往往就出在编译前没装openssl-devel或者系统的 openssl 版本太老。Python 3.10 的 ssl 模块要求 OpenSSL 1.1.1 以上而 CentOS 7 默认的 openssl 是 1.0.2k不够用。这个问题我先埋个伏笔后面“常见问题”部分详细讲。除了 openssl这几个库也值得留意readline-devel装完这个Python 交互式命令行才能用方向键查找历史命令否则按上下键会出现乱码。sqlite-develPython 内置 sqlite3 模块依赖它Django 等框架默认数据库迁移脚本会用到。libffi-develcffi 库和 Python 标准库里的ctypes都靠它很多 C 扩展的 Python 包必须用。zlib-develpip 安装包时处理压缩数据依赖它缺失会导致tarfile解压失败。总之这一步多花两分钟后面至少少折腾两小时。2.3 下载 Python 3.10 源码包并校验源码不建议去乱七八糟的第三方网站下载直接到 Python 官方 FTP 下cd /usr/local/src wget https://www.python.org/ftp/python/3.10.11/Python-3.10.11.tgz我推荐用 3.10.11这是 Python 3.10 的最终维护版本比 3.10.0 到 3.10.10 修复了大量 bug新装环境没必要选旧版。下载完解压tar xzf Python-3.10.11.tgz cd Python-3.10.11习惯上我会顺手校验一下文件完整性防止下载过程损坏wget https://www.python.org/ftp/python/3.10.11/Python-3.10.11.tgz.asc gpg --verify Python-3.10.11.tgz.asc Python-3.10.11.tgz不过国内网络环境下访问 python.org 可能有点慢如果下载超时可以用华为云、阿里云上的 Python 镜像目录路径结构一致速度更快。校验签名不是必须步骤但如果你是在生产环境装花一分钟做一下更放心。3. 核心实操编译安装全流程3.1 configure 参数怎么选影响有多大进入源码目录后第一步是执行 configure。这一步会根据你当前系统的环境生成 Makefile决定后续编译行为。我用的命令是./configure --prefix/usr/local/python3.10 \ --enable-optimizations \ --with-ensurepipinstall这三个参数的含义我得逐个说一下因为你如果不懂它们后面出了问题都不知道该怪谁--prefix指定安装目录这个最重要。我装在/usr/local/python3.10所有配套命令、库文件都在这下面卸载时直接删目录不污染系统。--enable-optimizations会启用 PGOProfile-Guided Optimization也就是编译时先跑一遍测试程序根据运行数据做针对性优化。好处是装出来的 Python 运行速度更快代价是编译时间会翻倍甚至三倍。我第一次没经验开着这个参数在低配服务器上编译硬生生等了四十分钟。如果机器性能一般或者你只是想在测试环境快速装一个可以去掉这个参数。--with-ensurepipinstall则是让安装过程自动带上 pip省得后面手动装。需要说明的是configure 执行完后会输出一段配置摘要里面会显示你系统里检测到的几个关键库比如OpenSSL、libffi、zlib。建议你花十秒扫一眼如果看到no说明对应模块没编进去这时候返回去补装依赖库再重新 configure比装完再折腾省事得多。3.2 编译与安装的完整命令序列configure 没问题后开始正式编译。这段命令我建议直接整段复制make -j$(nproc) make altinstall-j$(nproc)是让 make 用 CPU 的所有核心并行编译能明显缩短编译时间。如果你不确定服务器有几个核可以先执行nproc看下输出。如果编译过程中报错先别急着重试往下看“常见问题”部分。make altinstall跟make install的区别我前面提过这里再强调一次install 会把 Python 可执行文件安装成python3如果系统原本没有 python3 还好但在 CentOS 7 上某些系统脚本或第三方软件可能已经创建了python3软链直接覆盖很容易弄崩依赖。而altinstall生成的是python3.10、pip3.10这种带完整版本号的命令不会去改python3。编译完成后可以确认一下安装结果ls /usr/local/python3.10/bin/正常情况下能看到python3.10、pip3.10、pip3、python3.10-config等文件。这里注意pip3也会生成但因为它在独立的/usr/local/python3.10/bin/目录里并不影响系统其它路径下的 pip。3.3 软链接与 PATH 配置altinstall装完默认情况下你直接敲python3.10是找不到命令的因为/usr/local/python3.10/bin不在 PATH 里。有两种处理办法我更推荐做软链ln -s /usr/local/python3.10/bin/python3.10 /usr/local/bin/python3.10 ln -s /usr/local/python3.10/bin/pip3.10 /usr/local/bin/pip3.10这样所有用户都能直接用python3.10命令不用改每个用户的 PATH。如果你希望设置成默认的python3我建议你要想清楚因为 CentOS 7 默认没有 python3把它作为默认 python3 影响不大但 CentOS 8/9 自带的 3.6/3.9 就不要覆盖了。想长期使用的话也可以把/usr/local/python3.10/bin加进 PATH 环境变量echo export PATH/usr/local/python3.10/bin:$PATH /etc/profile.d/python310.sh source /etc/profile.d/python310.sh这种做法的好处是不产生软链文件目录本身就是独立的管理更干净。两种方式任选其一我实际更习惯软链因为执行which python3.10时路径清晰一眼能看出来源。验证一下安装结果python3.10 -V pip3.10 -V输出Python 3.10.11和对应的 pip 版本安装就成功了。3.4 虚拟环境项目隔离才是正经事装完 Python 3.10 之后我强烈建议所有项目都使用虚拟环境而不是直接往全局环境里pip install。原因很简单不同项目依赖的包版本可能互相冲突比如 A 项目要 Django 3.2B 项目要 Django 4.2全装在一个环境里迟早出事。创建虚拟环境用标准库的 venv 就行不需要额外装 virtualenvcd /opt mkdir myapp cd myapp /usr/local/python3.10/bin/python3.10 -m venv venv source venv/bin/activate激活后命令行前面会出现(venv)前缀这时候敲python和pip用的都是虚拟环境里的 3.10跟系统环境完全隔离。后续项目部署时可以直接在 systemd 服务里指定虚拟环境里的 Python 绝对路径比source activate更可靠ExecStart/opt/myapp/venv/bin/python /opt/myapp/app.py这一步在写 Dockerfile 或写启动脚本时特别有用后面扩展方案里我再细说。4. 常见问题与排查技巧实录4.1 pip 安装时报 SSL 模块不可用怎么破这是 CentOS 7 上编译 Python 3.10 遇到频率最高的坑没有之一。现象是Python 编译安装一切正常python3.10 -V也正常但一执行pip3.10 install requests直接报错Could not fetch URL ... There was a problem confirming the ssl certificate或者更干脆地提示ModuleNotFoundError: No module named _ssl。原因我也提到过CentOS 7 自带的 OpenSSL 是 1.0.2k而 Python 3.10 要求至少 1.1.1。你会发现 configure 的时候日志里 OpenSSL 那一行是no但 configure 并不会因此中止它只是默默地去掉了 ssl 模块等你装完才发现 pip 废了。解决办法是重新编译一个高版本 OpenSSL再回过头来重新编译 Python。我在服务器上的操作步骤是cd /usr/local/src wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz tar xzf openssl-1.1.1w.tar.gz cd openssl-1.1.1w ./config --prefix/usr/local/openssl --openssldir/usr/local/openssl shared zlib make -j$(nproc) make install等 OpenSSL 装好重新回到 Python 源码目录加上两个参数重新 configure然后重新 makecd /usr/local/src/Python-3.10.11 make clean ./configure --prefix/usr/local/python3.10 \ --enable-optimizations \ --with-ensurepipinstall \ --with-openssl/usr/local/openssl \ --with-openssl-rpathauto make -j$(nproc) make altinstall--with-openssl指定我们新编译的 OpenSSL 路径--with-openssl-rpathauto让 Python 在运行时自动找到对应的动态库否则编译过了运行也会因为找不到 libssl.so 报错。重新编译后再执行pip3.10 install就正常了。这个坑我踩过两次现在不管装什么版本的 Python凡是 CentOS 7我都默认先把 OpenSSL 升到 1.1.1 再编译一次成型。4.2 编译到一半卡死或被 kill多半是内存不够加了--enable-optimizations之后编译过程会额外执行一段 profiling 测试这段时间内存占用会明显上涨。我在一台内存只有 1G 的小服务器上试过一次make跑到一半直接被 OOM Killer 干掉日志显示Killed或make: *** [Python] Error 137没有任何明确报错很迷惑。排查方法很简单编译前敲一下free -h看看剩余内存。如果机器内存小于 2G我建议直接去掉--enable-optimizations或者用make -j1单核编译降低内存峰值。不要硬扛你是在部署环境不是在跑基准测试优化那点性能收益远不如先把业务跑起来重要。等以后机器配置升了再重新编译也不迟。4.3 系统 Python 被误改yum 直接崩溃怎么救还有一个不少新手会犯的错误装完 Python 3.10 后手一抖把/usr/bin/python软链接指向了 Python 3.10或者干脆把/usr/bin/python2.7给删了。结果第二天执行yum install nginx发现 yum 报错No module named yum。原因是 yum 本身是用 Python 2 写的你把默认 python 换成 3.10它自然找不到 yum 模块了。这种问题处理起来不复杂但要冷静ls -l /usr/bin/python*看看软链是不是被改了。如果/usr/bin/python指向了别的路径把它恢复回来ln -sf /usr/bin/python2.7 /usr/bin/python万一/usr/bin/python2.7已经被删了就需要从系统安装盘或镜像仓库里把这个包恢复出来。CentOS 7 上对应的 RPM 包是python-2.7.5-90.el7.x86_64.rpm下载后用rpm -ivh重新装回即可。安装时注意别和现有的系统文件冲突必要时候加--force。这里的关键经验就是这个错误能别踩就别踩把系统自带的 Python 当“系统文件”而不是“编程工具”任何新的 Python 版本都用独立目录装。4.4 常见异常速查表嫌上面内容太长不好记的可以直接收藏这个表现象可能原因处理办法No module named _sslOpenSSL 版本低于 1.1.1 或 openssl-devel 未装编译安装 OpenSSL 1.1.1重新 configure 并指定--with-opensslmake中途被 OOM Kill内存不足PGO 测试占用过高去掉--enable-optimizations或降低并行度-j1bash: python3.10: command not found未配置软链接或 PATH添加/usr/local/python3.10/bin到 PATH或创建软链yum报No module named yum/usr/bin/python被错误覆盖恢复/usr/bin/python软链指向 python2.7ModuleNotFoundError: No module named sqlite3缺 sqlite-devel安装 sqlite-devel 后重新编译pip install下载速度极慢默认访问官方 PyPI 源配置国内 PyPI 镜像源如果用国内源pip 可以这样配置pip3.10 config set global.index-url https://mirrors.aliyun.com/pypi/simple/配置好之后pip 的下载速度会有一个质的提升尤其是安装 pandas、numpy 这种大包时差别非常明显。5. 替代方案与经验建议5.1 pyenv开发机多版本管理利器如果你是在本地开发机上做测试需要在 Python 3.9、3.10、3.11 之间来回切换那我更推荐用 pyenv而不是反复源码编译。pyenv 是一个用户级的 Python 版本管理工具安装后可以一条命令装任意版本curl https://pyenv.run | bash pyenv install 3.10.11 pyenv local 3.10.11pyenv 在编译底层逻辑上跟我上面写的源码编译是一样的所以依赖库同样不能少重点还是 gcc、openssl-devel、libffi-devel 这些。它的优势是版本切换非常干净pyenv local 3.10.11设置完当前目录下python命令就自动变成 3.10.11去别的目录又切回原来的版本适合个人电脑。但生产服务器我一般不用 pyenv因为多一层工具就会多一个故障点而且 systemd 启动脚本指定解释器路径时pyenv 版本下的路径不直观。5.2 Docker 方案从根上避开环境问题如果你有 Docker 环境最省心的方式其实是根本不装 Python 到宿主机直接用官方镜像。这样 CentOS 宿主机只负责跑容器Python 版本、依赖库都在镜像里固化换台机器也能复现同样的环境。一个最基础的三行 Dockerfile 就能解决FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ COPY . . CMD [python, app.py]构建docker build -t myapp:latest . docker run -d --name myapp -p 8000:8000 myapp:latest镜像方式我特别推荐给那些需要统一团队开发环境、或者运维要批量部署多个 Python 项目的场景。宿主机不用跑一堆编译工具链也不用担心污染系统 Python干净利落。当然如果你的服务器没有 Docker或者因为安全策略不让用容器那就老老实实按前面的源码编译走。5.3 我的几条实操心得最后说几个我这么多年在 CentOS 上装 Python 总结出来的经验可能比前面的命令更值钱第一装 Python 之前先改 yum 源。不换国内源的话光groupinstall Development Tools这一步就能让你等到怀疑人生。第二把编译命令写成一个 shell 脚本存到本地。比如install_python310.sh下次在新机器上部署直接改一下版本号执行十几分钟搞定不用现场回忆命令。脚本里记得把依赖安装、源码下载、configure、make、软链全部串起来。第三生产环境不要只留一个 Python 3.10。你以后很可能还要装 Python 3.11 甚至 3.12目录规划时一定要带版本号比如/usr/local/python3.10、/usr/local/python3.11并行的放那里互不影响。第四pip 安装包之前先做镜像源配置。这个建议放前面或后面都行反正别忘不然首次pip install就会让你见识到什么叫网络超时。第五每次编译完一定要做一次完整验证不光是python3.10 -V还要顺手python3.10 -c import ssl, sqlite3, ctypes; print(ok)确认关键模块都在。这一个小动作能帮你避免下个月突然发现某个功能不可用的尴尬。我在实际部署里最常用的一句话是编译 Python 不难难的是别让这次安装影响系统的其他部分。只要记住“独立目录、altinstall、虚拟环境”这三个关键词你装的就不是一个孤零零的解释器而是一套稳定、可维护的 Python 运行环境。
返回列表