1. 为什么要在树莓派上折腾Python版本这件事
树莓派这玩意儿,玩过的人都知道,它出厂自带的系统里往往预装了一个Python版本,比如Raspberry Pi OS Bookworm默认带的是Python 3.11,Bullseye带的是3.9。平时写写小脚本、点个灯、读个传感器,系统自带的版本完全够用。但一旦你开始做稍微正经一点的项目,比如跑YOLOv5推理、搞量化交易回测、用某些只支持特定Python版本的库,问题就来了——版本不对,pip装不上,或者装上了跑起来各种报错。
更麻烦的是,树莓派上Python的安装方式跟普通Linux桌面不太一样。你可能同时存在系统自带的/usr/bin/python3、手动编译安装的/usr/local/bin/python3.x、还有用pyenv管理的版本。这三者混在一起,PATH一乱,你就分不清到底在跑哪个。这时候“卸载指定版本”就不是一个可选项,而是一个必须做的清理动作。
我见过太多人在这上面翻车:有人直接rm -rf /usr/bin/python3,结果整个系统工具链崩了,连apt都用不了;有人用apt remove python3,把桌面环境都带走了。所以这篇文章,我把自己在树莓派4B和树莓派5上反复折腾Python版本管理的经验整理出来,从判断当前环境、选择卸载方式、到清理残留、修复依赖,一步步说清楚。不管你是刚入门的Python新手,还是已经在树莓派上部署过多个项目的开发者,这些内容都能帮你少走弯路。
2. 动手之前先搞清楚:你的Python到底装在哪
2.1 树莓派上Python的三种存在形式
在树莓派上,Python的安装来源大致分三类,每一类的卸载方式完全不同,搞混了就是灾难。
第一类是系统包管理器安装的Python。这是Raspberry Pi OS自带的,通过apt管理,装在/usr/bin/下面。比如/usr/bin/python3.11,它跟系统的很多工具绑定在一起,apt、add-apt-repository、甚至桌面环境的某些组件都依赖它。这类Python绝对不能随便卸载,卸载了系统基本就废了。
第二类是手动编译安装的Python。你从python.org下载源码,./configure --prefix=/usr/local编译安装,最终落在/usr/local/bin/python3.x。这类Python跟系统隔离得比较好,卸载相对安全,但要注意/usr/local/lib/python3.x/下面的site-packages残留。
第三类是版本管理工具管理的Python。比如pyenv,它把版本装在~/.pyenv/versions/下面,每个版本独立目录,卸载就是删目录加pyenv rehash,最干净。还有conda/miniconda,装在~/miniconda3/envs/下面,用conda remove处理。
提示:在树莓派上,我强烈建议用pyenv来管理多版本Python,而不是手动编译到
/usr/local。原因后面会详细说。
2.2 一条命令看清当前Python的全貌
在动手卸载之前,先跑几条命令把家底摸清楚。这一步花两分钟,能省你两小时的重装系统时间。
# 查看当前默认python3指向哪里 which python3 # 查看所有python相关的可执行文件 ls -la /usr/bin/python* /usr/local/bin/python* 2>/dev/null # 查看当前python3版本 python3 --version # 查看python3的安装位置和sys.path python3 -c "import sys; print(sys.executable); print('\n'.join(sys.path))" # 如果用了pyenv pyenv versions 2>/dev/null # 如果用了conda conda env list 2>/dev/null这几条命令跑完,你基本能画出当前系统的Python分布图。重点看sys.executable输出的路径,那就是你当前实际在用的Python解释器位置。
2.3 判断哪些Python不能动
有一个简单粗暴的判断方法:凡是/usr/bin/下面的Python,默认都当成不能动的。你可以验证一下:
# 查看哪些系统包依赖python3 apt-cache rdepends python3 | head -30 # 查看python3这个包被哪些包依赖 apt-cache depends python3你会看到一大堆系统工具依赖它。在树莓派上,python3这个apt包是python3-minimal、python3-distutils、raspi-config等一堆东西的依赖项。你apt remove python3,apt会告诉你将要删除几百个包,其中可能包括桌面环境。看到那个提示的时候,千万别按Y。
3. 不同安装方式的卸载实操
3.1 卸载apt安装的Python版本(极度谨慎)
先说结论:除非你明确知道自己在做什么,否则不要卸载apt安装的Python。但有些特殊情况,比如你确实需要把系统自带的Python 3.9换成3.11,而且愿意承担风险,那可以按下面的思路来。
首先,不要直接apt remove python3。正确的做法是先安装新版本,再把默认指向切过去,最后才考虑移除旧版本。在树莓派上,可以用deadsnakes PPA或者从源码编译新版本。
如果你确实要移除某个特定小版本(比如系统里同时有python3.9和python3.11,想删掉3.9),可以这样做:
# 先模拟一下,看看会删掉什么 apt-get remove --dry-run python3.9 # 如果确认影响可控,再执行 sudo apt-get remove python3.9 # 清理不再需要的依赖 sudo apt-get autoremove但我要提醒你,在Raspberry Pi OS上,python3.9往往不是一个独立的apt包,而是python3.9-minimal、libpython3.9-stdlib、libpython3.9-minimal等一组包。你remove的时候要一起处理,否则会留下半残状态。
注意:执行
apt-get autoremove之前,一定要仔细看它列出的待删除列表。树莓派上经常出现autoremove把raspi-config或者wolfram-engine(如果你装了)带走的情况。
3.2 卸载手动编译安装的Python
手动编译安装的Python,通常落在/usr/local/下面。卸载步骤相对清晰,但要注意清理干净。
假设你当初是这样安装的:
./configure --prefix=/usr/local --enable-optimizations make -j4 sudo make altinstall用的是altinstall而不是install,所以可执行文件是python3.9而不是覆盖python3。卸载的时候:
# 进入当初编译的源码目录 cd /path/to/Python-3.9.x # 执行卸载(如果Makefile还在) sudo make uninstall如果源码目录已经删了,那就手动清理:
# 删除可执行文件 sudo rm -f /usr/local/bin/python3.9 sudo rm -f /usr/local/bin/pip3.9 # 删除库文件 sudo rm -rf /usr/local/lib/python3.9 # 删除头文件 sudo rm -rf /usr/local/include/python3.9 # 删除man page sudo rm -f /usr/local/share/man/man1/python3.9.1 # 删除pkg-config文件 sudo rm -f /usr/local/lib/pkgconfig/python-3.9.pc手动清理最大的坑是漏删。比如/usr/local/lib/python3.9/site-packages/下面可能装了一堆第三方库,你只删了/usr/local/lib/python3.9,但site-packages里如果有软链接指向别处,就会留下悬空链接。建议删完之后跑一遍:
# 查找所有残留的python3.9相关文件 sudo find /usr/local -name "*python3.9*" 2>/dev/null sudo find /usr/local -name "*Python-3.9*" 2>/dev/null3.3 用pyenv卸载指定Python版本(推荐方式)
如果你当初是用pyenv装的,那卸载就是最舒服的:
# 查看已安装版本 pyenv versions # 卸载指定版本 pyenv uninstall 3.9.16 # 如果当前global或local设置的是这个版本,需要重新设置 pyenv global 3.11.4pyenv uninstall本质上就是删除~/.pyenv/versions/3.9.16整个目录,然后更新shims。干净利落,不留残留。这也是我为什么推荐在树莓派上用pyenv的原因——树莓派的存储卡读写速度有限,手动编译一次Python要很久,用pyenv管理可以避免重复编译,卸载也简单。
3.4 用conda卸载Python环境
如果你用的是miniconda或anaconda:
# 查看所有环境 conda env list # 删除整个环境 conda env remove -n myenv # 如果只是想降级某个环境里的Python版本 conda install -n myenv python=3.9conda的卸载是环境级别的,删掉整个环境目录即可。但要注意,conda在树莓派上的性能一般,尤其是树莓派4B的4GB内存版本,跑conda有时候会卡。我个人的建议是,树莓派上能用pyenv就用pyenv,conda留给那些确实需要科学计算栈的场景。
4. 卸载后的清理与系统修复
4.1 清理pip残留和缓存
卸载Python本体之后,pip的缓存和用户级安装的包往往还在。这些东西不清掉,占空间不说,还可能干扰新版本的pip。
# 清理pip缓存 rm -rf ~/.cache/pip # 清理用户级安装的包(如果确定不再需要) rm -rf ~/.local/lib/python3.9 rm -rf ~/.local/bin/pip3.9 # 查看还有哪些python相关的命令 compgen -c | grep -E "^python|^pip" | sort -u4.2 修复被破坏的软链接
手动卸载最容易出问题的地方是软链接。比如/usr/bin/python3原本指向python3.9,你删了3.9,这个链接就断了。修复方法:
# 查看断掉的链接 sudo find /usr/bin /usr/local/bin -xtype l 2>/dev/null # 重新指向可用的python3 sudo ln -sf /usr/bin/python3.11 /usr/bin/python3如果/usr/bin/python3本身被删了,而系统工具又依赖它,那就麻烦了。这时候可以用apt-get install --reinstall python3-minimal来恢复。但前提是apt还能用。如果apt也挂了,那就只能从另一台树莓派或者用chroot的方式修复,或者直接重刷系统。
4.3 更新PATH和shell配置
卸载完Python,别忘了检查shell配置文件里有没有写死的路径:
# 检查这些文件里有没有python相关的PATH设置 grep -n "python" ~/.bashrc ~/.profile ~/.bash_profile /etc/profile 2>/dev/null如果有类似export PATH="/usr/local/python3.9/bin:$PATH"这样的行,要删掉或者改成新版本路径。改完之后source ~/.bashrc生效。
4.4 验证系统工具是否正常
卸载完Python之后,跑一遍系统工具,确认没有把依赖搞坏:
# 测试apt sudo apt update # 测试raspi-config sudo raspi-config --help # 测试python3是否还能用 python3 -c "print('hello')" # 测试pip pip3 --version如果apt update报错说找不到python3,那说明你把系统Python删了,需要赶紧恢复。恢复方法取决于你删的程度,最坏情况是重刷系统。
5. 常见问题与排查速查表
5.1 卸载Python后apt报错怎么办
这是最常见的问题。症状是运行apt或apt-get时提示/usr/bin/python3: No such file or directory。原因是apt的某些组件是用Python写的。
解决方法分两种情况。如果/usr/bin/python3只是软链接断了,但实际的python3.11还在,那就重建链接:
sudo ln -sf /usr/bin/python3.11 /usr/bin/python3如果实际的Python二进制也被删了,那就需要重新安装:
# 如果apt还能跑 sudo apt-get install --reinstall python3-minimal python3 # 如果apt也跑不了,用dpkg直接装 sudo dpkg -i /var/cache/apt/archives/python3-minimal*.deb如果连dpkg都跑不了,那就只能从另一台相同系统的树莓派上拷贝/usr/bin/python3.x过来,或者重刷系统。
5.2 卸载后pip命令找不到
pip通常是跟着Python一起装的。如果你卸载了Python 3.9,但pip3还指向3.9,那就会报错。解决方法是重新安装pip:
# 确保python3可用 python3 --version # 重新安装pip sudo apt-get install --reinstall python3-pip # 或者用ensurepip python3 -m ensurepip --upgrade5.3 虚拟环境里的Python怎么卸载
如果你是用python3 -m venv myenv创建的虚拟环境,卸载就是删目录:
rm -rf myenv但要注意,虚拟环境里的pyvenv.cfg文件记录了基础Python的路径。如果你删了基础Python,虚拟环境也会失效。所以正确的顺序是:先删虚拟环境,再卸载基础Python。
5.4 树莓派上哪些Python版本是安全的
根据我的经验,在Raspberry Pi OS上:
| 版本来源 | 路径 | 能否卸载 | 风险等级 |
|---|---|---|---|
| apt安装的系统Python | /usr/bin/python3.x | 不建议 | 极高 |
| 手动编译安装 | /usr/local/bin/python3.x | 可以 | 中 |
| pyenv管理 | ~/.pyenv/versions/ | 可以 | 低 |
| conda环境 | ~/miniconda3/envs/ | 可以 | 低 |
| 虚拟环境 | 项目目录下 | 可以 | 低 |
5.5 卸载后磁盘空间没释放
有时候你删了Python,但df -h看空间没怎么变。原因可能是:
- pip缓存没清:
~/.cache/pip可能占几百MB - 编译残留:
/tmp下面可能有编译时的临时文件 - 日志文件:
/var/log/下面可能有相关日志
# 查看大目录 sudo du -sh /usr/local/lib/python* 2>/dev/null du -sh ~/.cache/pip 2>/dev/null # 清理 sudo apt-get clean rm -rf ~/.cache/pip6. 我的实操心得与避坑建议
6.1 树莓派上管理Python版本的最佳实践
折腾了这么多回,我现在的做法是:系统自带的Python绝对不动,所有项目用的Python都用pyenv装。具体流程:
# 安装pyenv依赖 sudo apt-get install -y make build-essential libssl-dev zlib1g-dev \ libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \ libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev \ libffi-dev liblzma-dev # 安装pyenv curl https://pyenv.run | bash # 配置环境变量 echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc echo 'eval "$(pyenv init -)"' >> ~/.bashrc source ~/.bashrc # 安装指定版本 pyenv install 3.11.4 pyenv global 3.11.4这样系统Python负责维持系统运转,pyenv的Python负责你的项目。两者互不干扰,卸载也简单。
6.2 编译Python时的参数选择
如果你确实需要手动编译,树莓派上建议加这些参数:
./configure --prefix=/usr/local \ --enable-optimizations \ --enable-shared \ --with-ensurepip=install--enable-optimizations会做PGO优化,编译时间翻倍但运行速度快10%到20%。--enable-shared生成共享库,某些场景需要。--with-ensurepip=install确保pip一起装上。
但要注意,--enable-optimizations在树莓派4B上编译一次可能要40分钟到1小时,树莓派5快一些,大概20分钟。如果你只是临时用用,可以不加这个参数。
6.3 卸载前一定要做的备份
在动系统Python之前,我强烈建议先备份关键配置:
# 备份pip列表 pip3 freeze > ~/pip-backup-$(date +%Y%m%d).txt # 备份apt的python相关包列表 dpkg -l | grep python > ~/dpkg-python-backup.txt # 备份重要的虚拟环境路径 ls -la ~/ | grep venv > ~/venv-list.txt这样即使卸载出问题,你至少知道原来装了什么,重装的时候有个参考。
6.4 树莓派5上的注意事项
树莓派5用的是更新的内核和更快的IO,但Python版本管理的基本逻辑没变。需要注意的是,树莓派5的Raspberry Pi OS默认可能是Python 3.11,而且系统对Python的依赖更深。我在树莓派5上试过卸载系统Python,结果比树莓派4B更容易出问题,因为树莓派5的一些新硬件驱动工具是用Python写的。
所以树莓派5上,我的建议更保守:只动pyenv和虚拟环境,系统Python碰都不要碰。
6.5 一个真实的翻车案例
去年我在一个树莓派4B上做YOLOv5部署,需要Python 3.8,但系统自带的是3.9。我图省事,直接apt remove python3.9,然后想装3.8。结果apt把python3-distutils、python3-apt、raspi-config全带走了。重启之后桌面直接进不去,SSH也连不上,最后只能拔卡重刷。
从那以后,我再也不动系统Python了。需要特定版本,一律pyenv或者Docker。Docker在树莓派上也是个好选择,docker run -it python:3.8,环境隔离得彻彻底底,卸载就是docker rmi。
6.6 用Docker替代直接卸载的思路
如果你只是需要某个特定版本的Python跑一个项目,其实不一定非要卸载现有的。用Docker可以完全绕过版本冲突:
# 拉取指定版本的Python镜像 docker pull python:3.8-slim # 运行容器 docker run -it --rm -v $(pwd):/app -w /app python:3.8-slim bash这样你的树莓派系统Python完全不受影响,项目跑在容器里,版本随便选。卸载的时候docker rmi python:3.8-slim就完事了。树莓派4B跑Docker没问题,树莓派5更流畅。
7. 卸载后的Python环境重建
7.1 重新安装pip和基础工具
卸载完旧版本,装好新版本之后,第一件事是把基础工具装上:
# 确保pip可用 python3 -m ensurepip --upgrade # 升级pip python3 -m pip install --upgrade pip # 安装常用工具 python3 -m pip install --upgrade setuptools wheel virtualenv在树莓派上,virtualenv比venv有时候更好用,因为它对旧版本Python的兼容性更好。但如果你用的是Python 3.11以上,venv完全够用。
7.2 重建虚拟环境
如果你之前有项目依赖特定的虚拟环境,卸载Python后需要重建:
# 进入项目目录 cd ~/myproject # 创建新虚拟环境 python3 -m venv venv # 激活 source venv/bin/activate # 重装依赖 pip install -r requirements.txt如果requirements.txt里有版本冲突,可以用pip install --no-deps逐个排查。树莓派上有些包需要编译,比如numpy、opencv-python,建议先用apt装系统级的依赖:
sudo apt-get install -y python3-numpy python3-opencv这样pip就不用从头编译,省时间。
7.3 验证新环境
重建完之后,跑一个简单的测试脚本,确认环境正常:
# test_env.py import sys import platform print(f"Python版本: {sys.version}") print(f"可执行文件: {sys.executable}") print(f"系统架构: {platform.machine()}") print(f"系统版本: {platform.version()}") # 测试常用库 try: import numpy as np print(f"NumPy版本: {np.__version__}") except ImportError: print("NumPy未安装") try: import cv2 print(f"OpenCV版本: {cv2.__version__}") except ImportError: print("OpenCV未安装")跑通这个脚本,说明基础环境没问题。然后再跑你的项目代码,逐个解决依赖问题。
7.4 树莓派特有的GPIO库兼容性
树莓派上很多项目依赖RPi.GPIO或gpiozero。这些库对Python版本有要求。比如RPi.GPIO在Python 3.11上可能需要从源码编译:
# 安装编译依赖 sudo apt-get install -y python3-dev # 从源码安装RPi.GPIO pip install RPi.GPIO --no-binary :all:gpiozero的兼容性更好,纯Python实现,直接pip装就行。如果你用的是树莓派5,注意RPi.GPIO可能不兼容,需要用lgpio或gpiozero的新版本。
8. 长期维护:让Python版本管理不再头疼
8.1 建立版本管理规范
我现在给自己定了几条规矩,分享出来供参考:
- 系统Python只用于系统工具,不装任何第三方库
- 每个项目独立虚拟环境,虚拟环境放在项目目录下
- 需要多个Python版本时,用pyenv管理,不用apt
- 定期清理不再使用的虚拟环境和pyenv版本
- 重要项目用Docker封装,环境完全隔离
这套规矩执行下来,我再也没遇到过版本冲突的问题。
8.2 定期清理脚本
写个简单的清理脚本,每月跑一次:
#!/bin/bash # cleanup_python.sh echo "清理pip缓存..." rm -rf ~/.cache/pip echo "清理pyenv不再使用的版本..." # 列出所有版本,手动确认后删除 pyenv versions echo "清理apt缓存..." sudo apt-get clean sudo apt-get autoremove -y echo "查找悬空的python软链接..." sudo find /usr/bin /usr/local/bin -xtype l 2>/dev/null | grep python echo "当前磁盘使用情况:" df -h /这个脚本不自动删东西,只是把需要关注的点列出来,你手动决定删什么。安全第一。
8.3 记录环境变更
每次卸载或安装Python版本,我都会在~/python-changelog.md里记一笔:
## 2024-01-15 - 卸载pyenv 3.9.16 - 安装pyenv 3.11.4 - 切换global到3.11.4 - 重建了myproject的虚拟环境 - 影响:myproject的numpy从1.21升级到1.24这个习惯看起来麻烦,但当你三个月后回来跑一个老项目,发现跑不起来的时候,翻一下这个记录,能快速定位问题。
8.4 树莓派存储卡的寿命考虑
树莓派的存储卡读写寿命有限,频繁编译Python会加速卡的老化。所以:
- 尽量用pyenv的预编译版本,减少编译次数
- 编译时用
-j4充分利用多核,缩短编译时间 - 考虑把pyenv的versions目录放到外接SSD上,减少对TF卡的写入
- 定期备份重要环境配置,卡挂了能快速恢复
我在树莓派4B上把~/.pyenv软链接到了外接USB SSD,编译速度快了不少,TF卡的压力也小了。树莓派5支持NVMe SSD,那就更舒服了。
8.5 最后再分享一个小技巧
如果你不确定某个Python版本能不能安全卸载,可以用apt-get remove --dry-run先模拟一遍。但更稳妥的方法是,在卸载之前,先用dpkg -S查一下这个Python相关的文件属于哪个包:
# 查看/usr/bin/python3.9属于哪个包 dpkg -S /usr/bin/python3.9 # 查看这个包被哪些包依赖 apt-cache rdepends python3.9-minimal如果依赖列表里有一堆系统关键包,那就别动了。如果只有你自己装的几个包,那可以考虑卸载。这个判断方法比凭感觉靠谱得多。
另外,树莓派社区里经常有人问“怎么把树莓派400的TF卡内容完整复制到另一张更大的卡”,其实这跟Python版本管理也有关系。你如果在旧卡上折腾了一堆Python版本,复制到新卡之后,路径和软链接可能对不上。所以复制之前,最好先把Python环境清理干净,只保留必要的版本,这样迁移过去问题最少。