Jetson Nano上替代Anaconda的Python环境管理方案
如果你手里有一块 Jetson Nano又习惯在服务器上用 Anaconda 管理 Python 环境把这两件事放到一起体验大概率会滑铁卢。Jetson Nano 的核心是 ARM 处理器存储和内存都按嵌入式设备的“省”字来设计。而 Anaconda 是一个面向桌面和服务器 x86 环境设计、动不动占好几个 GB 的整套发行版。让 Anaconda 在 Jetson Nano 上跑相当于让一个西装革履的办事员挤在自行车后座上去开会——不是不能走但每一步都很费劲。这篇文章不打算劝你继续忍。我会结合自己在多块 Jetson Nano 上的实践聊聊它上面可用的环境管理工具替代方案venv、Miniforge、uv、Poetry讲清楚它们各自适合什么场景、怎么装、怎么用以及替换 Anaconda 之后踩过的坑和解题思路。无论你是刚拿到开发板的新手还是想给现有项目换个更清爽的环境管理方式这篇都值得读完再动手。1. Jetson Nano 上 Python 环境管理的真实痛点1.1 为什么 Anaconda 在 Jetson Nano 上很别扭第一体积。完整的 Anaconda 安装包超过 3GB安装解压之后还要再膨胀数倍。Jetson Nano 的存储通常是 16GB 板载存储或者一张 32GB、64GB 的 SD 卡官方系统镜像装完CUDA 相关的底层库再落一次地剩下的空间已经很局促。如果你还要放模型权重、数据集和源码再塞一个 Anaconda写代码就像在行李箱里再塞一套冬装——不是塞不下是以后每天都在为空间发愁。第二依赖求解速度。conda 的经典动作“Solving environment”在普通 PC 上就经常让人等得没脾气在 Jetson Nano 的四核 ARM CPU 上更是直接放大这个缺点。我试过在板子上用 conda 创建一个包含几十个包的深度学习环境进度条在“Solving environment”上跳了十几分钟期间 CPU 占用率拉满而 pip 那边同等工作量早就装完了。对于开发板这种性能敏感的设备这个等待会直接消磨掉你调试的耐心。第三ARM 架构的生态问题。Anaconda 默认频道对 aarch64 的支持远没有对 x86_64 那么全面。很多你依赖的包往往只在 conda-forge 频道有 ARM 版本而 conda 又经常按自己的逻辑解析频道优先级结果就是装一半报“找不到匹配版本”干瞪眼。再加上 Jetson Nano 的深度学习环境通常是围绕官方预编译库构建的这些库和 Anaconda 自己带进来的 glibc、libstdc 容易版本错位表现出来的就是“明明装好了一 import 就崩”。第四也是最容易被忽视的一点Jetson Nano 上跑深度学习最优路径是直接用系统里适配好的 CUDA、cuDNN再叠加官方预编译的 PyTorch wheel。但 Anaconda 倾向于把一整套运行时从自己的目录里一起打包带进来当 conda 里的库和系统底层库发生冲突时静态环境的优势反而变成了劣势。我以前见过不少用户装完 Anaconda 后 torch 怎么都 import 不了最后发现是 conda 把系统里某个 x86 库的路径覆盖到了 ARM 环境的搜索路径上这种问题排查起来极其痛苦。1.2 环境管理工具在这块板子上应该优先满足什么所以在 Jetson Nano 这个特殊的硬件环境里挑选环境管理工具的标准和 PC 上是完全不同的。我的优先级排序是这样的存储占用越低越好。系统要跑 CUDA、深度学习库存储空间非常金贵。依赖解析速度在 ARM 小核上快速、确定的解析比什么都强。与系统底层库的兼容性能不碰系统自带的 CUDA、OpenCV 就尽量别碰。可复现性SD 卡一坏、一换卡要能快速重建环境。维护成本板子上往往就一个人折腾复杂的配置方案只会变成无人维护的坑。一句话环境管理工具在你手里应该是轻量搬运工而不是第二个“系统”。基于这个判断我后面逐一拆解几个真正能在 Jetson Nano 上跑得顺的方案。2. 替代方案选型四种主流工具怎么选2.1 venv——最朴素也最省心的兜底venv 是 Python 自带的虚拟环境工具不需要额外安装任何东西在 Jetson Nano 官方镜像里直接用python3 -m venv就能创建环境。它的核心逻辑很简单复制一套 Python 解释器的路径结构然后把 pip 安装的包都放进这个独立目录里和系统全局的 site-packages 隔离开。在 Jetson Nano 上我最常用的姿势是加上--system-site-packages参数这样虚拟环境会继续共享系统里已经装好的 numpy、OpenCV、CUDA 相关 Python 绑定。这个做法的好处是系统镜像里已经适配好的底层库直接复用不用在环境里重新编译和踩坑坏处是如果将来你需要给某个项目装一个和系统版本不同的 numpy可能会互相覆盖。所以我通常只建议在“跑官方预编译深度学习栈”这个场景下用这个参数。venv 的缺点也很明显它不负责 Python 版本管理系统是什么版本环境里就是什么版本。如果项目非要 Python 3.7 而系统自带的是 3.8venv 就无能为力了。不过对大多数 Jetson Nano 场景来说系统自带的那个 Python 版本恰恰是和官方 CUDA 库配合得最好的版本反而没必要换来换去。2.2 Miniforge——想要 conda 生态但不想背整套重量级发行版如果你确实喜欢 conda 那种“环境里可以指定 Python 版本、channel 一键装包”的体验Miniforge 是最接近 Anaconda 但更合理的替代。它和 Anaconda 用的是同一套 conda 核心但不预装任何用不上的科学计算包安装完只有 conda、python 以及最小集体积比 Anaconda 小一个数量级。更重要的是Miniforge 默认使用 conda-forge 作为主要软件源而 conda-forge 对 aarch64 架构的支持要比 Anaconda 默认频道好得多。在 Jetson Nano 上这意味着你创建环境时大概率能找到对的 ARM 版本包而不是折腾半天后提示“Package not found”。Miniforge 还顺带解决了 conda 速度慢的问题因为它通常内置了 mambamamba 用 C 重写了依赖求解器速度比原生 conda 快很多。后面我会专门演示 mamba 的用法。要是你想尝试 conda 又不是非 Anaconda 不可Miniforge 就是那个最平滑的降落点。2.3 uv——用 Rust 速度把 pip 体验拉满的新工具uv 是一款用 Rust 写的 Python 包管理器它和 pip 的兼容性做得非常好可以直接读 requirements.txt、pyproject.toml也能直接创建 venv 环境。它在 Jetson Nano 这类弱 CPU 设备上的优势主要体现在两点一是安装包时解析依赖的速度非常快二是自身是一个独立二进制不依赖系统 Python 环境装起来非常干净。实际使用中我经常用uv venv替代python3 -m venv用uv pip install替代pip install。尤其是在一个大项目里改了几行依赖、需要反复装包验证时uv 的缓存和并发下载能让整体耗时从“等杯咖啡”缩短到“打个哈欠”。而且 uv 也支持 Python 版本管理需要不同 Python 版本时可以手动指定比纯 venv 灵活。它的短板是项目相对年轻一些老的工作流插件和它配合还不太成熟。不过对 Jetson Nano 这种偏单项任务的场景来说uv 的“快”就是最大的生产力。2.4 Poetry——面向长期项目的依赖管理方案Poetry 和上面几个工具定位不太一样它更像个“项目管家”管理的是整个项目的依赖、打包、发布全流程。它用 pyproject.toml 声明依赖用 poetry.lock 锁定精确版本保证团队协作或者跨设备部署时每个人装出来的环境完全一致。如果你在 Jetson Nano 上维护的是一个正经的长期项目比如一个推理服务、一个视觉检测 Demo需要反复迭代并且要出可复现的部署包Poetry 的价值就体现出来了。你可以把依赖写在 pyproject.toml 里用poetry install一键重建环境再也不用手动 pip freeze 再比对 requirements.txt。不过 Poetry 在 Jetson Nano 上的安装会比 venv 或 uv 重一些它本身是纯 Python 写的安装后第一次执行还要做一定的解析。如果项目不大或者只是临时做实验我建议还是优先考虑更轻的方案一旦项目复杂到需要锁定传递依赖Poetry 再上场也不迟。2.5 横向对比与我的推荐组合工具安装复杂度存储占用依赖解析速度Python 版本管理适合场景venv无需安装极小快走 pip不支持快速实验、系统 Python 直接隔离Miniforge中等较小快mamba支持想用 conda 生态、多版本需求uv低极小极快支持追求速度和可复现性Poetry中等较小中等间接支持长期项目、需要 lock 锁定我在 Jetson Nano 上的最终组合很简单日常实验和深度学习 Demo 全部使用 venv pip不折腾其他东西一旦需要多版本 Python 或者想体验 conda 的 channel 便利就用 Miniforge mamba剩下追求极致的包安装速度时用 uv 来替代 pip 流程。Anaconda 在板子上我基本不会再碰。3. 实操在 Jetson Nano 上从零搭一套环境3.1 动手前先检查系统状态不管选哪个方案第一步都不是急着装工具而是把系统底数摸清楚。官方镜像是基于 ARM 架构的 Linux 系统Python 版本和依赖库都是预编译好的先确认这些基础信息能省掉后面不少麻烦。uname -m python3 --version df -h free -huname -m输出应该是aarch64确认你在 ARM 环境下操作后续所有包都必须找对应 ARM 版本。python3 --version记录系统自带 Python 的具体版本这是后续 venv 环境的基础。df -h看剩余磁盘空间如果已经用了 80% 以上建议先清理系统缓存再考虑装环境管理工具。free -h注意内存容量后面跑大模型或者装大包时心里有数。然后检查系统是否已经装了 pip 和 venvpython3 -m pip --version python3 -m venv --help如果提示没有 pip先装一下sudo apt update sudo apt install python3-pip python3-venv这里特别提醒一句不要在系统层面乱装包尽量所有项目依赖都放进虚拟环境里。板子上系统 Python 经常被底层工具依赖一个不小心的 pip 升级就可能把系统环境弄坏。3.2 方案 Avenv pip 组装一个干净的深度学习环境这套方案是我在 Jetson Nano 上用得最多的步骤就几条命令。先创建一个共享系统库的环境python3 -m venv --system-site-packages ~/venvs/torch source ~/venvs/torch/bin/activate加--system-site-packages的意思是让虚拟环境可以访问系统 site-packages 里已有的库这样就不用在环境里重新装一遍。对跑深度学习来说系统镜像自带的 numpy、OpenCV、CUDA 绑定等都能直接复用省时省力。然后升级 pip 并安装 PyTorch 系列的预编译版本pip install --upgrade pip pip install torch torchvision在官方镜像对应的 pip 源里上面命令会自动拉取适配 Jetson Nano 的预编译 wheel不需要自己折腾编译。装完验证一下python -c import torch; print(torch.__version__) python -c import torch; print(torch.cuda.is_available())如果输出True说明 CUDA 接上了。我遇到最多的问题就是有人忘了先激活环境直接pip install torch结果装到系统 Python 里接着又是一堆权限和版本冲突。记住一个原则先source再pip。这套方案的“干净”体现在哪儿呢环境里的包和系统是隔离的系统出问题不会带崩项目项目出问题也不会污染系统。想要丢弃环境的时候直接rm -rf ~/venvs/torch就完了不需要像卸载 Anaconda 那样清理半天注册项和 shell 配置。3.3 方案 BMiniforge 管理多版本 Python 环境如果你确实需要不同 Python 版本或者 conda-forge 里的某些包Miniforge 是不错的补充。安装它不用 root直接下载官方给 ARM 架构的安装脚本wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh bash Miniforge3-Linux-aarch64.sh -b -p $HOME/miniforge3-b表示静默安装-p指定安装目录。装完之后不要急着把 conda 写进.bashrc我更喜欢手动 sourcesource $HOME/miniforge3/etc/profile.d/conda.sh conda activate这样每次新开 shell 不会自动进入 base 环境也就不会出现“conda 加载半天影响其他操作”的体验。需要创建指定 Python 版本的环境时mamba create -n py38 python3.8 numpy opencv conda activate py38用 mamba 创建是因为它对 aarch64 的包索引和依赖解析速度都要好很多。创建完环境后conda activate py38切换即可。要注意的是Miniforge 环境里的 Python 和系统 Python 是两套独立运行时如果安装的包需要和底层 CUDA 库联动尽量用 conda-forge 里有预编译的版本避免现场编译。还要注意 conda 和 venv 同时存在时别把 PATH 弄混。我的习惯是Miniforge 里面装纯 Python 依赖和 conda 生态的包系统原生 CUDA 相关的链接通过环境变量或者包自身的 abi 去对接不强行在 conda 环境里重新造轮子。3.4 方案 Cuv 快速重建项目依赖uv 的安装最简单一条命令curl -LsSf https://astral.sh/uv/install.sh | sh也可以把它当作普通 pip 工具装在系统里但直接装二进制更干净。装完后uv命令就全局可用了。创建环境uv venv ~/venvs/uvtest --python 3.8 source ~/venvs/uvtest/bin/activate如果你只想用 uv 加速安装不创建自己的环境也可以直接在当前激活的 venv 里用uv pip install -r requirements.txtuv 会自动读取当前虚拟环境路径不需要你再手动指定。它还有一个很实在的功能同一个项目反复装包时缓存命中率高后续 install 几乎是秒级完成。Jetson Nano 上网络和磁盘 IO 都不算快这功能对反复调试依赖配置的人来说非常友好。顺便说uv 也可以直接读 pyproject.tomluv pip install -e .这样正式项目里依赖声明和安装流程都能统一起来。3.5 环境导出、备份与跨卡迁移环境管理不只是“创建”更重要的是“重建”。在 Jetson Nano 上SD 卡损坏、换卡、迁移项目都是家常便饭所以我每次都把环境描述文件固定下来。venv / pip 系pip freeze requirements.txt恢复时python3 -m venv --system-site-packages ~/venvs/proj source ~/venvs/proj/bin/activate pip install -r requirements.txtMiniforge / conda 系conda env export environment.yml恢复时mamba env create -f environment.ymlPoetry 系直接提交pyproject.toml和poetry.lock新机器上poetry install即可。迁移的时候有个铁律换 SD 卡或者换板子时系统镜像版本要尽量一致。Jetson Nano 底层库和系统库是绑定的如果你在一张卡上用了官方镜像的某一版另一张卡用的是新版CUDA 库版本对不上之前的环境导出文件即便原样导入也可能跑不起来。所以我一般会先写好一个setup_env.sh脚本脚本里固化系统源、Python 版本、pip 源和所有依赖清单一条命令把环境从零复制到新卡上。4. 常见问题与排查技巧实录4.1 conda 依赖求解卡死怎么办最典型的场景是你用原生 conda 创建环境或者安装包终端一直停在“Solving environment”风扇狂转不结束。这个问题的根源是 conda 的经典求解器在线性规划上算得太慢尤其在 aarch64 的包索引不完整时更加严重。我的处理方法是优先用 mamba。Miniforge 安装的时候通常已经内置了 mamba如果找不到可以先mamba install mamba -c conda-forge后面所有conda install都换成mamba install。如果 mamba 也存在再检查频道优先级。conda config --show channels看清当前有哪些源尽量把 conda-forge 放第一位避免出现包版本搜索冲突。还有一招是“定点安装”mamba install python3.8 numpy1.19.5把大版本直接交代清楚求解器搜索空间变小速度会快很多。不要老用mamba install python numpy这种宽泛写法在 ARM 环境里求解器会把你的 CPU 烧穿。4.2 pip 装进系统 Python 而不是虚拟环境这个问题非常隐蔽你输入pip实际指向的是系统 Python 的 pip结果装了一堆包到系统目录后面再 import 发现版本冲突或者权限错误。Jetson Nano 官方镜像默认可能没有启用虚拟环境很多人习惯性敲pip install包就这样污染了系统。排查方法很简单which pip pip --version如果路径是/usr/bin/pip或者/usr/local/lib/python3.8/dist-packages这类说明你在系统层操作。正确做法是每次工作前先source虚拟环境再看which pip确认路径指向~/venvs/xxx/bin/pip再安装。如果已经污染了系统环境可以这样清理把误装进系统的包名找出来用sudo apt-get install --reinstall python3-xxxx把系统包恢复然后再也不用裸 pip。这类问题通常不需要重刷系统但过程麻烦最好还是从源头避免。4.3 aarch64 下找不到预编译包在 Jetson Nano 上装包最常听到的报错是ERROR: Could not find a version that satisfies the requirement xxx这通常意味着你需要的包在当前 Python 版本、当前架构下没有现成的 wheel而源码编译又可能因为缺系统库而失败。我的排查路径是这样的先上 conda-forge 搜一搜有没有 aarch64 构建conda search xxx -c conda-forge如果 conda-forge 也没有就考虑从源码编译pip install --no-binary :all: xxx但在 Jetson 上源码编译要准备编译链sudo apt install build-essential cmake编译前还要看包的依赖是否完整经常是少了某个底层库导致编译报错fatal error: xxx.h: No such file or directory。这时候不要硬刚去项目的文档里查一下官方对 aarch64 的编译建议通常有预先要装的系统依赖清单。多数情况下我建议优先选用 Jetson 官方镜像里已经预制好的包比如 PyTorch、OpenCV、TensorRT 之类不要自己从通用 PyPI 源硬装更容易踩 ARM 的坑。4.4 OpenCV 装完 import 崩溃很多人在 Jetson Nano 上直接执行pip install opencv-python然后import cv2直接段错误或者白屏窗口问题往往出在通用 wheel 缺少 GStreamer、V4L2、CUDA 等系统能力支持。通用 PC 上这个 wheel 能用因为实际调用的是系统桌面库但 Jetson 上是嵌入式环境摄像头采集、硬件解码需要特定驱动通用 wheel 根本没编译这些模块。我的建议是优先使用系统镜像里的 OpenCV 实际验证一下python3 -c import cv2; print(cv2.__version__)如果系统自带 OpenCV 可用在 venv 里用--system-site-packages参数复用即可或者在创建环境后手动把系统 OpenCV 路径链接进来。如果你想在 conda 环境里用可以用 conda-forge 的版本试一试mamba install opencv -c conda-forge总之不要为了省事随便pip install opencv-python。这个坑在 aarch64 上几乎是必踩项。4.5 重启后环境丢失或错乱Jetson Nano 上我遇过不少次这种诡异现象昨天创建好的 venv 今天 source 后Python import 的却是系统库或者 conda activate 直接提示环境不存在。排查看起来是环境目录没了实际上是 shell 初始化和环境变量优先级的问题。先说 conda如果你当初运行过conda init它会把 conda 代码写进~/.bashrc然后默认激活 base。这个 base 一旦激活会改变 PATH让系统 Python 被 conda 的 Python 覆盖。要解决我记得最有效的办法是conda config --set auto_activate_base false这样新开 shell 不会自动进入 base环境切换完全手动逻辑清晰。venv 的常见问题是环境目录被剪贴或者移动过。venv 的 bin 目录里都是绝对路径一旦移动位置就无法再 activate会报错。所以我从一开始创建时就会把环境固定在一个不会被随意清理的路径下比如~/venvs/。如果需要迁移直接删除旧环境、根据 requirements.txt 重建而不是试图搬 or 改路径。4.6 问题速查表症状常见原因快速解法conda 求解卡死原生 conda 求解器太慢改用mamba install并指定精确版本pip 装到系统层没激活虚拟环境which pip查看路径source 后再装aarch64 找不到包没有对应 wheel查 conda-forge、源码编译或换官方预编译版本cv2 import 崩溃通用 wheel 缺少系统能力用系统 OpenCV 或 conda-forge 版本重启后环境消失conda base 自动激活或 venv 被移动关闭 auto_activate_base、固定环境路径这块板子最特殊的地方就在于它的软件栈高度定制不能拿 x86 服务器的那套习惯硬套。环境管理工具本身不是目标让项目能够稳定、快速、可复现地跑起来才是目标。我个人在折腾过无数轮之后的体会是Jetson Nano 上的环境管理核心思路应该是“减少系统级的惊喜”——越是复杂的工具越容易在一个不熟悉的架构上制造更多变量。venv 打底、uv 加速、Miniforge 兜底已经覆盖了我遇到的所有场景。最后再分享一个小习惯给每块板子写一个setup_env.sh把系统源、基础库、Python 版本、依赖安装全部固化进去。SD 卡炸了、换新板子一条命令就能回到能干活的现场。这个脚本比你收藏的任何教程都靠谱因为它是你根据自己实际项目定制的。