ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux源码编译安装Python完整指南:独立环境与避坑实践

Linux源码编译安装Python完整指南:独立环境与避坑实践 说实话每次看到网上全是“Linux安装Python只需要一条命令”的说法我都想把人拽到服务器前看看。在Linux里装Python这件事说简单也简单说麻烦是真的能让你心态爆炸。系统自带的Python可能是2.x也可能是被系统工具死死绑定的3.x如果你直接apt install python3装完以为万事大吉后面就会发现包版本老、pip装什么都报错、系统脚本还会莫名其妙挂掉甚至yum直接罢工。这篇文章不聊虚的直接讲在Linux中安装Python的几种主流方案、源码编译的完整流程、为什么我强烈推荐你装独立版本而不是动系统环境以及我在一堆服务器上反复踩过的坑。无论你是刚上手Linux的新手还是需要在生产环境部署Python的运维和开发下面这些内容都值得认真看一遍。1. 装之前先想清楚版本、路径和安装方式怎么选1.1 为什么系统自带的Python不能直接用绝大多数Linux发行版都自带了Python但这里的“自带”分两种情况。一种是CentOS/RHEL系列自带的是Python 2.7而且系统核心工具比如yum、早期的ansible、部分监控脚本都依赖它。你在CentOS 7上直接运行python出来的版本是2.7运行python3则会提示找不到命令或者只有极老的3.x版本。另一种是Ubuntu/Debian系列自带Python 3.x但版本相对保守例如Ubuntu 20.04自带Python 3.8Ubuntu 22.04自带Python 3.10。问题在于业务代码往往需要更新的特性比如Python 3.11里的异常组、3.12里的类型参数语法。你当然可以去换系统源、升级系统包但这样做的风险极高——系统级工具和Python的版本是有绑定关系的你把系统的Python 2.7删了或者把Python 3.8覆盖成3.11轻则yum不可用重则整个系统进入奇怪的状态。现实里最稳妥的方案永远是给业务单独装一份Python路径与系统Python完全隔离通过PATH或者绝对路径来调用。这也是我这篇文章从头到尾想强调的核心不要碰系统Python不要碰系统Python不要碰系统Python。1.2 三种主流的安装方式各自适合什么场景在Linux上装Python主流方式其实就是三个方向你可以根据场景直接选系统包管理器安装比如apt install python3、yum install python3。优点是快依赖自动解决版本由发行版仓库决定。缺点是版本落后而且包管理器会把它放到系统路径下部分发行版限制pip直接装全局包。适合只想要一个能跑脚本的简单环境比如快速跑个批量工具。源码编译安装从Python官网下源码包自己configure、make、install。优点是完全可控可以指定安装目录、选择需要的模块、得到任何一个版本甚至可以打上性能优化参数。缺点是耗时长需要提前装一堆编译依赖对新手不算友好。但这恰恰是我在生产环境最推荐的方式后面会细讲。版本管理工具安装典型代表是pyenv可以一键安装多个Python版本并随时切换。优点是在同一台机器上同时维护多个项目、多个版本特别方便缺点是pyenv本身也是一层需要维护的东西而且所有版本都放在用户目录下天然避开了系统Python的冲突。适合个人开发机、测试环境。这三条路不是互斥的。我自己平时开发会开pyenv上服务器部署绝对用源码编译应急的时候直接apt/yum装。明白每一种方式适合什么场景才是真正解决问题的开始。1.3 路径规划才是最容易忽视的细节很多人装Python只看版本号完全不管装到了哪里之后就会出现“我已经装了3.11为什么python3还是3.6”这种疑似灵异事件。实际上Linux加载命令时靠的是PATH环境变量系统默认的PATH里如果有/usr/bin它优先于你新装的/usr/local/python-3.11/bin那么shell自然还是找旧的那一个。我的建议是源码编译时用独立的前缀目录比如/usr/local/python-3.11.3/然后在/etc/profile.d/里新建一个脚本把这个目录的bin放到PATH最前面同时不覆盖系统的python链接。这样你执行python3时命中的就是我们新装的版本而系统的/usr/bin/python3还能继续服务系统工具两边互不打扰。记住这个思路后面很多怪毛病都能迎刃而解。2. 新手友好且最可靠源码编译安装完整流程2.1 先把编译工具链和依赖装齐源码编译Python之前第一件要做的事是装好编译工具和运行库。很多人直接跳过这一步就开始./configure结果编译到一半报错或者编译出来的Python缺失关键模块最典型的就是pip装不了包。如果你是Debian/Ubuntu系列先执行sudo apt update sudo apt install -y build-essential zlib1g-dev libffi-dev libssl-dev libbz2-dev libreadline-dev libsqlite3-dev tk-dev libgdbm-dev liblzma-dev如果你是CentOS/RHEL系列执行sudo yum groupinstall -y Development Tools sudo yum install -y openssl-devel bzip2-devel libffi-devel readline-devel sqlite-devel zlib-devel tk-devel这里每一个包都不是白装的我简单说一下它们的作用方便你以后遇到问题能反查build-essential/Development Tools提供gcc、g、make等编译工具这是编译一切的基石。zlib1g-dev/zlib-develPython的zip压缩、压缩包模块依赖它少了它你会发现某些模块无法导入。libffi-dev/libffi-develctypes模块依赖很多第三方库比如部分密码学库要用到。libssl-dev/openssl-devel这个最关键pip走HTTPS、ssl模块都靠它。很多人编完Python之后pip提示“ssl module is not available”十有八九是这块没装好。libreadline-dev/readline-devel交互式命令行里能用方向键翻历史、调整光标装完Python的交互模式才顺手。libsqlite3-dev/sqlite-develPython内置sqlite3模块需要它不少Django项目的数据库初始迁移也会用到。tk-dev/tk-develtkinter GUI模块如果你不需要写可视化程序可以省略但我习惯一并装上省得以后临时要用再重编。2.2 下载源码包和版本选择源码包直接去Python官网下载选择你需要的稳定版本。我的建议是优先用当前Active的稳定版比如3.10、3.11、3.12避免用即将EOL的版本。下载格式选.tgz就行体积小方便上传到内网服务器。cd /usr/local/src wget https://www.python.org/ftp/python/3.11.3/Python-3.11.3.tgz tar xf Python-3.11.3.tgz cd Python-3.11.3有人说国内访问python.org慢那你也可以用国内镜像站下载比如清华源提供的python安装包镜像路径结构是一样的https://mirrors.tuna.tsinghua.edu.cn/python/3.11.3/Python-3.11.3.tgz。下载后建议校验一下文件哈希避免下载损坏。2.3 configure参数怎么选接下来是核心环节./configure --prefix/usr/local/python-3.11.3 --enable-optimizations先说--prefix。这个参数决定了Python最终安装到哪个目录。如果你想让业务Python和系统完全隔离必须显式指定它。我习惯用带版本号的目录这样不同版本可以共存切换也直观。再讲--enable-optimizations。它等价于开启PGOProfile-Guided Optimization编译器会用一些“代表性工作负载”跑一遍再优化理论上能让Python整体性能提升10%到20%。代价是编译时间翻倍而且多出好几轮测试执行。我的经验是生产环境如果机器性能允许就开只是个人用或者机器配置弱果断关掉省几十上百分钟。还有一些进阶参数比如./configure --prefix/usr/local/python-3.11.3 \ --enable-optimizations \ --enable-shared--enable-shared生成共享库libpython3.11.so一些需要嵌入Python或者链接libpython的场景会用到但也会让安装后的目录结构略有差异除非有明确需求否则不建议默认开启。另外特别提醒一点Python 3.11及以上对OpenSSL版本有硬性要求至少是OpenSSL 1.1.1。在CentOS 7上系统自带的OpenSSL是1.0.2直接configure会让Python编译出不含ssl模块的版本。解决办法是单独装一个高版本的OpenSSL再显式指定路径具体我在后面排查章节详细讲。2.4 编译安装与altinstall的玄机配置完成之后开始正式编译make -j$(nproc)-j$(nproc)的意思是使用CPU所有核心并行编译可以大幅缩短时间。如果机器内存不大并行度过高反而会导致内存不足此时建议直接make或者make -j2。编译完成之后关键的一步来了——不要用make install请用make altinstall。这两者有什么区别make install会把python3、pip3等不带完整版本号的软链接装到prefix目录可能会导致和系统命令产生混乱。make altinstall只安装带版本号的python3.11和pip3.11不创建容易引起歧义的通用链接。这个设计就是明确告诉你靠版本号调用是最安全的。make altinstall安装完成后验证一下/usr/local/python-3.11.3/bin/python3.11 -V /usr/local/python-3.11.3/bin/pip3.11 -V2.5 配置PATH和pip国内镜像二进制已经就位但还有个问题每次都要敲完整路径太麻烦了。我们需要把新版本Python暴露到PATH里同时又不污染系统环境。推荐在/etc/profile.d/下新建一个文件比如python311.sh内容如下export PATH/usr/local/python-3.11.3/bin:$PATH执行source /etc/profile.d/python311.sh或重新登录终端再执行python3.11 -V应该就有输出了。接下来配置pip镜像这一步在中国大陆环境尤其重要。不配置的话pip默认访问PyPI官方源慢到让你怀疑人生。直接用清华源或阿里源/usr/local/python-3.11.3/bin/pip3.11 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple配置完以后后续pip安装包的速度会有质的提升。2.6 别忘了建立venv虚拟环境最后我强烈建议你即使Python装好了也不要直接在全局环境里pip install包。你会在未来几个月里安装、升级、删除各种依赖全局环境迟早会变成一团乱麻。每次新建项目时用自带的虚拟环境模块隔离依赖cd /path/to/project /usr/local/python-3.11.3/bin/python3.11 -m venv venv source venv/bin/activate激活之后你当前的shell就会优先使用venv里的python和pip此时pip install安装的所有包都只会落在项目目录下的venv里想删就删想重建也毫无心理负担。VSCode里配置Python解释器时直接指向venv/bin/python也是同样的思路比你为了图省事用全局环境要省心得多。3. 其他实用路线系统包管理器与pyenv3.1 apt和yum安装建议与红线如果只是临时跑个小脚本或者想在开发机上快速有个Python环境用包管理器没有任何问题。Ubuntu/Debian上的命令是sudo apt update sudo apt install -y python3 python3-pip python3-venvCentOS/RHEL 8上的命令是sudo yum install -y python3包管理器装出来的Python版本由发行版定义。以Ubuntu 22.04为例装出来是Python 3.10虽然不算最新但对大多数脚本来说够用了。安装完成后使用python3而不是python因为很多发行版不创建python这个软链接此外还要注意PEP 668的限制后面会讲。这里有一条红线必须反复强调不要试图去替换系统Python。比如你执行sudo rm /usr/bin/python3或者强制把系统的Python软链接指向你自己编的版本这种做法一旦出错系统级的包管理器会瞬间失灵。你要新的版本就按第一节的方式装独立环境千万别碰系统的路径。3.2 pyenv一台机器管理十几个Python版本如果你需要在多个项目之间切换Python版本pyenv绝对是最顺手的工具。它不会动系统的Python所有版本都装在用户目录的.pyenv下运行时通过shim机制拦截命令并映射到正确的版本。安装pyenv最简单的办法是直接用它的自动安装脚本curl https://pyenv.run | bash装完后再把对应的环境变量写入~/.bashrc或~/.zshrcecho export PATH$HOME/.pyenv/bin:$PATH ~/.bashrc echo eval $(pyenv init -) ~/.bashrc source ~/.bashrcpyenv本身不携带有源代码安装Python版本时它会调用源码编译。所以前面那些编译依赖zlib、openssl、readline等依然需要提前装好否则pyenv install 3.11.3时照样报错。使用方式特别简单pyenv install 3.11.3 pyenv global 3.11.3 pyenv local 3.8.10pyenv global设置的是全局默认版本pyenv local则会在当前目录生成一个.python-version文件进入目录自动切到对应版本。在项目根目录跑一下pyenv local你就拥有了一个自动按项目走的环境切换目录都不用手动干涉。不过要提醒一下pyenv适合个人开发机如果你是在生产环境的服务器上尤其是多用户共用的一台机器我仍然建议走源码编译的独立目录方案避免每次部署都要靠某个用户的.bashrc才能找到正确的python。3.3 venv和conda到底选哪个不管你是用源码编译还是pyenv最终装依赖时还是要面临环境隔离的问题。最轻量的方案就是Python自带的venv。它没有额外依赖就是一份独立的解释器副本和site-packages目录创建快删除简单。如果你做的是数据分析、机器学习项目涉及大量科学计算包venv虽然能用但装numpy、pandas、scikit-learn这类包时在不同平台上经常需要轮子或依赖链当年装得相当痛苦。这种情况下选择conda或miniconda更省心它自带一套完整的二进制依赖管理创建环境时直接conda create -n ml python3.11 conda activate mlconda会把numpy、scipy等科学计算包的二进制依赖一并处理掉让我这种国内用户不用在gcc版本、BLAS库之间反复折腾。我的建议是普通web开发、写脚本、自动化用venv就够了数据分析、机器学习、频繁切换复杂科学计算环境直接用conda。两条路都能走通但选择顺手的那条才最舒服。4. 安装后的常见故障排查与避坑清单4.1 pip报“ssl module is not available”或TLS/SSL相关错误这是源码编译中最常见的坑没有之一。编译完成的Python可以启动一执行pip install就报错说pip is configured with locations that require TLS/SSL或者提示No module named ssl。根因是configure时没有找到可用的OpenSSL头文件和库。可能有两种情况一是没装openssl-devel相关包二是系统自带OpenSSL版本过低比如CentOS 7自带的OpenSSL 1.0.2新版Python 3.11编译时直接拒绝启用ssl模块。排查方式/usr/local/python-3.11.3/bin/python3.11 -c import ssl; print(ssl.OPENSSL_VERSION)如果报ImportError就对照第一节把openssl-devel补上如果是版本过低需要单独编译一个高版本OpenSSL安装到独立目录再configure Python时显式指定./configure --prefix/usr/local/python-3.11.3 \ --with-openssl/usr/local/openssl-1.1.1 \ --with-openssl-rpathauto--with-openssl-rpathauto是为了让生成的Python在运行时自动找到openssl的共享库避免启动时报找不到libssl.so.1.1。4.2 安装完成后python3.11命令找不到明明安装过程没有报错但执行python3.11 -V就是提示命令不存在。这种情况基本上都是PATH没配好。用以下命令确认安装目录是否存在ls -l /usr/local/python-3.11.3/bin/python3.11如果存在就开始排查PATH。执行echo $PATH看看有没有/usr/local/python-3.11.3/bin。没有就把2.5节的环境变量配置补上并确保source之后重新打开终端。还有一种隐蔽情况是你把PATH写进了~/.bashrc但通过systemd服务或者cron去运行python时那些环境默认不加载用户配置所以最好把PATH配置写到/etc/profile.d/下对所有用户和大部分服务生效。4.3 Debian/Ubuntu系统pip安装包时提示externally-managed-environment新版Debian12和Ubuntu23.04用PEP 668机制默认锁住系统Python禁止直接用pip往系统环境里装包报错信息大概是“externally-managed-environment”。这其实不是故障而是系统在保护自己。你的应对方式是优先使用venv创建虚拟环境在虚拟环境里pip install就不会再有这个提示。如果你想强行用全局环境装pip也给了一个参数--break-system-packages但我的建议是不到万不得已不要用毕竟你手动改全局包和系统包发生冲突的代价完全不值得。4.4 make编译到一半失败提示Killed或内存不足源码编译Python算是一个比较吃资源的操作--enable-optimizations更是让这个过程雪上加霜。如果你用的是内存较小的VPS或云主机比如1G内存make -j$(nproc)时可能会触发OOM编译进程直接被系统杀掉。两种解决办法一种是关掉PGO优化改用./configure --prefix...不带--enable-optimizations。另一种是编译时不加-j参数或者限制并行度make -j1同时临时加一点swapsudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile编译成功后如果不想保留swap可以顺手关掉。4.5 手贱改了系统软链接导致yum只能用怎么急救假如你不小心动了系统的Python软链接导致yum/dnf直接不可用先别慌。千万别用sudo yum去重装Pythonyum本身都跑不动了。直接恢复软链接ls -l /usr/bin/python3找到系统原本的版本比如CentOS 7是python3.6那就执行ln -sf /usr/bin/python3.6 /usr/bin/python3如果连Python解析器都找不到那么用/usr/bin/python2.7去手动重新触发rpm或者从安装光盘进行修复。这种场景最能印证我反复强调的那句话自己的独立Python用PATH隔离系统的Python一个软链接都别动。4.6 安装某Python版本后第三方库源码编译报错这类问题往往不是Python本身的问题而是缺少Python编译时的头文件。比如安装psutil、bcrypt等包含C扩展的库需要Python的开发头文件Python.h但有些参数组合下编译出来的Python不会自带头文件。用源码编译安装其实默认会带上头文件所以这种情况更多出现在apt/yum安装的场景。如果是Ubuntu需要额外安装python3-devsudo apt install -y python3-dev要是用venv装的某个Python还是报缺失就检查一下你是不是在虚拟环境里把site-packages里的部分文件删掉了重建一次虚拟环境往往是最快的解决方式。最后再分享几点我个人的习惯写了这么多最后聊点我自己的习惯吧。我在服务器上装Python规律基本固定先看系统版本CentOS这边二话不说编译独立版本Ubuntu这边看场景——临时跑工具用apt正式服务必编译。编译前先把openssl相关依赖装到位配置时带上--prefix和版本号目录make altinstall然后全局配置PATH和环境变量。装完第一件事不是急着跑业务代码而是先做两件小事一是把pip3.11 config set的国内源写好二是建好一个最小的venv跑一遍pip install requests确认整个网络、SSL、依赖链路都通了才继续。我还习惯把每次安装时的configure参数记到项目文档里这样半年后重建环境时不会因为想不起来当初怎么编的而抓瞎。你在实践中如果遇到这本书里没写到的怪问题欢迎按你的实际场景去反查依赖项和configure日志很多谜底就藏在日志里。多装几次、多踩几个坑这套流程对你来说就会像吃饭喝水一样自然。
返回列表