Ubuntu 22.04 安装 Apache MXNet 1.9.1 指南
在 Ubuntu 22.04 服务器上从零安装 Apache MXNet 1.9.1 的完整实录,涵盖 Python 3.8 环境搭建、numpy 版本兼容处理、系统依赖排障与卸载清理方法。
Ubuntu 22.04 安装 Apache MXNet 1.9.1 指南
一、安装目标与总体思路
本文记录在一台干净的 Ubuntu 22.04 服务器上安装 Apache MXNet 1.9.1(官方最终版本)的完整过程。与一般教程不同,本文把安装过程中真实出现的每一条报错与对应修复动作都如实记录下来,读者按照本文操作时如果遇到相同的报错,可以直接对照处理。
总体安装路线是:系统准备(更新软件源、安装基础工具)→ 通过 deadsnakes PPA 安装 Python 3.8 → 创建独立虚拟环境(venv)→ 安装兼容版本的 numpy → 安装 mxnet 1.9.1 → 补齐系统动态库依赖 → 验证导入与张量运算 → 记录卸载清理方法。
1.1 为什么必须用 Python 3.8
MXNet 1.9.1 在 PyPI 上分发的 manylinux wheel 包名是 mxnet-1.9.1-py3-none-manylinux2014_x86_64.whl,实测文件大小 49.1 MB。这个 wheel 的 Python 兼容级别实际只覆盖到 CPython 3.8/3.9:在 Ubuntu 22.04 自带的 Python 3.10.12 环境下直接执行 pip install mxnet==1.9.1,pip 会因为找不到匹配的 wheel 而尝试源码编译,并很快失败。因此第一步就是要获得一个 Python 3.8 解释器。在 Ubuntu 22.04 上获取 Python 3.8 最简便的方式是添加 deadsnakes PPA 软件源,该源由社区维护,提供了 Ubuntu 官方仓库未收录的各版本 Python 解释器。实测安装得到的版本是 Python 3.8.20。
1.2 版本兼容性结论(先说结论)
为了让读者少走弯路,这里先给出实测得出的版本组合结论,后文再展开每一步的验证过程:
- Python:3.8.x(实测 3.8.20)
- numpy:1.23.5(实测证明 1.24.4 会触发 np.bool 属性错误,必须降到 1.23.x)
- mxnet:1.9.1
- 系统库:libgomp1 与 libquadmath0 必须存在,否则 import 阶段直接失败
二、安装前必须理解的三个背景知识
在动手之前,先花一点篇幅讲清楚三个决定安装路线的背景知识,理解了它们,后文的每一步选择都会变得理所当然。这一节不涉及任何命令,但建议通读:安装类问题八成出在对这些机制的误解上。
2.1 wheel 与 manylinux:为什么会有版本门槛
PyPI 上的 Python 包通常以 wheel 形式分发。wheel 是一种预编译的分发格式,安装时无需本地编译,速度快且不受本地编译环境差异影响。但对于像 MXNet 这样包含大量 C++/CUDA 原生代码的包来说,wheel 里的动态库必须与解释器版本、CPU 架构、操作系统 C 库版本相匹配。Python 官方通过 ABI 标签标识这种兼容性:文件名中的 cp38 表示该 wheel 内含 CPython 3.8 扩展模块,py3-none-manylinux2014 则表示"纯 Python 分发、跨平台、基于 manylinux2014 基线构建"。mxnet 1.9.1 的 wheel 文件名是 mxnet-1.9.1-py3-none-manylinux2014_x86_64.whl,用的是 py3-none 标签,理论上不限定具体 Python 小版本,但实际上它的安装脚本在 pip 解析阶段会按 supported-python 声明过滤,1.9.1 只声明支持到 Python 3.8/3.9。所以在 Python 3.10 的 pip 眼里,PyPI 上根本不存在"属于自己的"mxnet 1.9.1 安装包,于是 pip 会下载源码包试图现场编译,而编译需要一整套 C++ 构建链与编译期依赖,几乎注定失败。理解了这一点就会明白:正确路线是准备一个 Python 3.8 解释器,而不是在 3.10 上强行安装。
2.2 manylinux2014 与系统动态库的关系
manylinux 是一个跨发行版的二进制兼容基线:wheel 构建环境把依赖的库都尽量打进去,但仍有少量系统级运行库假定目标机器上"本来就有",例如 OpenMP 运行时 libgomp、四精度数学库 libquadmath。这两者在桌面发行版上通常随编译器工具链安装而存在,但在精简的服务器镜像上可能缺失。后文排障实录中的前两个报错正源于此——pip 不负责系统库,wheel 不自带它们,只能由 apt 补齐。这也是 Linux 上 Python 包安装问题的一条通用排查思路:先分清报错发生在"Python 包层"还是"系统库层"。
2.3 为什么坚持用 venv
虚拟环境(venv)是 Python 官方内置的隔离机制,python3.8 -m venv /opt/mxnet-env 会在指定目录复制一份独立的解释器与 site-packages。选择 venv 而不是直接 pip 装进系统,有三个理由:其一,系统 Python 是 apt 管理的,往里面 pip 安装包会与包管理器互相踩踏,Ubuntu 22.04 之后的新版本 pip 甚至会直接拒绝(externally-managed-environment 保护);其二,本安装明确要求 numpy 1.23.5,而系统上其他 Python 工具链可能需要别的 numpy 版本,venv 让这种冲突从根源上消失;其三,venv 的卸载就是删目录,干净彻底,对"装了试试、不行就撤"的实验场景非常友好。后文所有 pip 命令均通过 /opt/mxnet-env/bin/pip 的绝对路径执行,这样即使不激活环境也不会装错位置。
3.1 确认系统版本
首先确认操作系统版本。本文实验环境是一台 Ubuntu 22.04.5 LTS 服务器,执行以下命令:
cat /etc/os-release | head -3
python3 --version
实测输出:
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
---
Python 3.10.12
可以看到系统自带的 Python 是 3.10.12,这正是 mxnet 1.9.1 的 wheel 无法直接安装的版本。如果输出与此不同(例如是 Ubuntu 20.04),本文后续的 PPA 路径与软件包命名可能会有差异,建议先统一到 Ubuntu 22.04 再继续。
3.2 更新软件源并安装软件源管理工具
添加 PPA 需要用到 add-apt-repository 命令,它由 software-properties-common 包提供。这个包通常不在最小化安装的默认集合里,需要先补装。apt-get update 的作用是刷新本地的软件源索引,让系统知道每个源上目前有哪些包、什么版本,这一步虽然看起来"什么都没装",但跳过它经常导致后续 apt-get install 报"Unable to locate package"或安装到过旧版本。执行以下两条命令(如需加速可配置 HTTP 代理环境变量):
sudo apt-get update
sudo apt-get install -y software-properties-common
实测执行后输出末尾为:
Running hooks in /etc/ca-certificates/update.d...
done.
这段输出表示软件源证书钩子执行完毕,属于 apt 更新 CA 证书时的正常收尾信息,看到它说明软件源准备工作已经就绪。
3.3 关于网络加速
如果服务器访问国际网络较慢,可以在命令前追加代理环境变量,例如:
export http_proxy=http://<代理地址>:<端口> https_proxy=http://<代理地址>:<端口>
代理地址与端口请替换为内网实际值,后文所有 apt 与 pip 命令在遇到下载缓慢时都可以用同样方式处理。除了代理,pip 还支持镜像源方式(后文 FAQ 中给出配置命令),apt 则可以选择国内发行版镜像站点。两种方式可以叠加使用,互不冲突。需要提醒的是,代理环境变量只在当前终端会话生效,新开终端需要重新 export,这也是很多人"上次明明能下载、这次又卡住"的常见原因;若希望长期生效,可以把 export 语句写入用户家目录的 .bashrc 文件末尾。
四、安装 Python 3.8(含真实排障实录)
4.1 添加 deadsnakes PPA
PPA(Personal Package Archive)是 Launchpad 平台提供的个人软件源机制。deadsnakes 团队长期为 Ubuntu 各 LTS 版本维护着几乎全部 Python 小版本的构建,是 Ubuntu 上安装非默认版本 Python 的事实标准做法。执行以下两条命令添加软件源并刷新索引:
sudo add-apt-repository -y ppa:deadsnakes/ppa
sudo apt-get update
add-apt-repository 会把源地址写入 /etc/apt/sources.list.d/ 目录下的独立文件(形如 deadsnakes-ubuntu-jammy.list),并自动导入签名密钥。使用 -y 参数是为了跳过确认提示,方便脚本化。第二条 apt-get update 是必须的:新添加的源只有经过一次索引刷新,apt 才"看得见"里面的包。执行完成后,可以用 apt-cache policy python3.8 查询该包的候选版本,确认它来自 deadsnakes 源。
4.2 安装 python3.8 与 venv 支持
sudo apt-get install -y python3.8 python3.8-venv
这里装了两个包:python3.8 是解释器本体;python3.8-venv 提供虚拟环境模块,Ubuntu 的发行习惯是把 venv 拆成独立包,不装它的话,后文 python3.8 -m venv 会报 ensurepip 相关错误。与 python3.8 一起被拉进来的还有 libpython3.8-stdlib、python3.8-minimal 等依赖包,apt 会自动处理。安装时建议带上 DEBIAN_FRONTEND=noninteractive 环境变量,原因见下一小节的排障实录。
4.3 排障实录一:tzdata 交互配置导致安装长时间卡住
实测中,这一步 apt 在处理 tzdata 包的配置脚本时长时间没有返回。tzdata 是时区数据库包,它的配置脚本会通过 debconf 前端询问用户所在时区,桌面终端里会弹出蓝色选择界面,但在无人值守或非交互终端下,标准输入没有内容也没有控制台,进程就会停在等待状态。通过 ps 查看,可以看到进程停留在 tzdata 的交互式配置前端:
root 4683 /usr/bin/dpkg --status-fd 28 --configure --pending
root 4685 /usr/bin/perl -w /usr/share/debconf/frontend /var/lib/dpkg/info/tzdata.postinst configure
root 4694 /bin/sh /var/lib/dpkg/info/tzdata.config configure
判断要点:apt-get 进程本身还在(不是死锁),但末端的 tzdata.config 子进程长时间无 CPU 消耗,基本可以确定是在等人输入。处理办法是:先终止卡住的交互进程,再以非交互模式补完 dpkg 配置。实测命令与输出如下:
kill -9 4694 4685
export DEBIAN_FRONTEND=noninteractive
sudo dpkg --configure -a
输出:
Setting up python3.8 (3.8.20-1+jammy1) ...
Setting up python3.8-venv (3.8.20-1+jammy1) ...
Processing triggers for libc-bin (2.35-0ubuntu3.14) ...
dpkg --configure -a 的含义是把所有处于"未配置完成"状态的包重新走一遍配置流程;在 DEBIAN_FRONTEND=noninteractive 下,tzdata 会取默认时区(UTC)而不再询问。看到 python3.8 与 python3.8-venv 的 Setting up 行,说明这两个包已正确配置完成。这条经验值得记住:在脚本或后台执行 apt 安装时,始终带上 DEBIAN_FRONTEND=noninteractive 环境变量,可以从源头避免这类交互等待。
4.4 验证 Python 3.8
python3.8 --version
实测输出:
Python 3.8.20
注意此时的系统默认 python3 仍然指向 3.10.12,两者互不干扰——这正是我们想要的状态:新版本解释器以并列方式共存,所有需要 3.8 的操作都显式调用 python3.8 命令,不去改动系统默认链接。强烈不建议用 update-alternatives 或改软链接的方式把系统 python3 强行指向 3.8,Ubuntu 22.04 的大量系统工具(如 apt 内部脚本、cloud-init 等)依赖默认解释器,改动它们极易引发系统级故障。
五、创建独立虚拟环境并安装依赖
5.1 创建 venv
把 MXNet 相关的一切隔离在独立的虚拟环境中,是避免污染系统 Python 的标准做法。实测创建路径为 /opt/mxnet-env:
python3.8 -m venv /opt/mxnet-env
创建完成后,/opt/mxnet-env 目录下会生成 bin、lib、include 等子目录:bin 里是这套环境专属的 python、pip 可执行文件;lib/python3.8/site-packages 是后续所有包的安装目标。创建完成后,后续所有 pip 命令都直接使用 /opt/mxnet-env/bin/pip 这个绝对路径调用,无需手动 source activate(当然也可以先执行 source /opt/mxnet-env/bin/activate 进入环境再操作,激活后命令提示符前会出现 (mxnet-env) 前缀,两种方式等价)。venv 的本质是"复制解释器 + 隔离包目录 + 重写路径的脚本",它并不复制标准库,因此空间开销很小,删除时也没有残留。
5.2 先装 numpy 并遇到第二个坑
MXNet 对 numpy 的版本声明是 numpy<2.0.0,>1.16.0(这一点在后文 pip 安装回显中可以确认)。表面上看,只要不超过 2.0 就行,于是先安装较新的 numpy,pip 默认解析到了 1.24.4:
/opt/mxnet-env/bin/pip install "numpy<2"
这里特意用带引号的关系表达式而不是裸写 numpy,是为了防止 shell 把 < 解释为重定向符——不加引号时,shell 会试图从名为"2"的文件读取标准输入,命令会直接报错。实测确认版本:
/opt/mxnet-env/bin/python -c "import numpy; print(numpy.__version__)"
输出:
1.24.4
此时一切看起来正常,numpy 1.24.4 满足 mxnet 声明的 <2.0.0 约束。但这个版本埋着后面第三个坑的伏笔。
5.3 安装 mxnet 1.9.1
/opt/mxnet-env/bin/pip install mxnet==1.9.1
实测完整输出(关键部分):
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting mxnet==1.9.1
Using cached https://pypi.tuna.tsinghua.edu.cn/packages/27/83/b307ad1f6e1ff60f8e418cb87f53646192681b417aadc1f40a345ba64637/mxnet-1.9.1-py3-none-manylinux2014_x86_64.whl (49.1 MB)
Requirement already satisfied: requests<3,>=2.20.0 in /opt/mxnet-env/lib/python3.8/site-packages (from mxnet==1.9.1) (2.32.4)
Requirement already satisfied: graphviz<0.9.0,>=0.8.1 in /opt/mxnet-env/lib/python3.8/site-packages (from mxnet==1.9.1) (0.8.4)
Requirement already satisfied: numpy<2.0.0,>1.16.0 in /opt/mxnet-env/lib/python3.8/site-packages (from mxnet==1.9.1) (1.24.4)
Requirement already satisfied: idna<4,>=2.5 in /opt/mxnet-env/lib/python3.8/site-packages (from requests<3,>=2.20.0->mxnet==1.9.1) (3.15)
Requirement already satisfied: charset_normalizer<4,>=2 in /opt/mxnet-env/lib/python3.8/site-packages (from requests<3,>=2.20.0->mxnet==1.9.1) (3.5.2)
Requirement already satisfied: certifi>=2017.4.17 in /opt/mxnet-env/lib/python3.8/site-packages (from mxnet==1.9.1) (2026.7.22)
Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/mxnet-env/lib/python3.8/site-packages (from requests<3,>=2.20.0->mxnet==1.9.1) (2.2.3)
Installing collected packages: mxnet
Successfully installed mxnet-1.9.1
从回显可以确认三件事:wheel 文件是 manylinux2014_x86_64 架构、体积 49.1 MB;mxnet 1.9.1 对 numpy 的约束是 numpy<2.0.0,>1.16.0;同时还会带上 requests、graphviz 等间接依赖。其中 graphviz 是 MXNet 可视化网络结构用的 Python 绑定(若需真正渲染结构图还要系统级 graphviz 工具,但仅 import 不需要)。pip 认为一切正常,但真正的考验在 import 阶段。
六、import 阶段的三连报错与逐一修复(真实排障实录)
安装成功不等于可用。mxnet 的导入过程要加载底层 C/C++ 动态库,这一阶段连续暴露了三个问题,每一个都如实记录如下。三个错误的排查顺序也有讲究:先是操作系统层的动态库缺失(OSError),再是 Python 包层的 API 兼容(AttributeError),层次分明,逐层收敛。
6.1 排障实录二:缺少 libgomp.so.1
第一次尝试导入:
/opt/mxnet-env/bin/python -c "import mxnet as mx; print(mx.__version__)"
报错:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/__init__.py", line 23, in <module>
from .context import Context, current_context, cpu, gpu, cpu_pinned
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/context.py", line 23, in <module>
from .base import classproperty, with_metaclass, _MXClassPropertyMetaClass
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/base.py", line 356, in <module>
_LIB = _load_lib()
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/base.py", line 347, in _load_lib
lib = ctypes.CDLL(lib_path[0], ctypes.RTLD_LOCAL)
File "/usr/lib/python3.8/ctypes/__init__.py", line 373, in __init__
self._handle = _dlopen(self._name, mode)
OSError: libgomp.so.1: cannot open shared object file: No such file or directory
从堆栈可以看出,Python 侧的 mxnet/init.py 一路导入到 base.py,执行 _load_lib() 时用 ctypes 的 CDLL 加载 libmxnet.so,动态链接器在这个阶段找不到 libgomp.so.1。libgomp 是 GCC 的 OpenMP 运行库,负责 MXNet 原生层的多线程并行调度,几乎所有科学计算类动态库都依赖它。安装 libgomp1 即可:
sudo apt-get install -y libgomp1
这个包体积很小(几百 KB),安装后无需任何配置,Python 侧也不需要重启什么服务,直接重新 import 验证即可。
6.2 排障实录三:缺少 libquadmath.so.0
装完 libgomp1 再次导入,报错前进了一步,换成缺另一个数学库:
OSError: libquadmath.so.0: cannot open shared object file: No such file or directory
libquadmath 是 GCC 的四精度浮点数学库(__float128 类型的支撑库),同样属于底层运行时。动态库加载是按依赖链逐层解析的,前一个补上后解析器才会继续检查下一个,所以这类"缺一个补一个"的过程是正常现象,不是反复出错。继续补装:
sudo apt-get install -y libquadmath0
6.3 排障实录四:numpy 1.24 的 np.bool 属性错误
补齐两个系统库后,第三次导入报出了第三个错误,这次是 Python 层面的:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/__init__.py", line 33, in <module>
from . import contrib
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/contrib/__init__.py", line 30, in <module>
from . import text
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/contrib/text/__init__.py", line 23, in <module>
from . import embedding
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/contrib/text/embedding.py", line 36, in <module>
from ... import numpy as _mx_np
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/numpy/__init__.py", line 23, in <module>
from .multiarray import *
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/numpy/multiarray.py", line 47, in <module>
from .utils import _get_np_op
File "/opt/mxnet-env/lib/python3.8/site-packages/mxnet/numpy/utils.py", line 37, in <module>
bool = onp.bool
File "/opt/mxnet-env/lib/python3.8/site-packages/numpy/__init__.py", line 305, in __getattr__
raise AttributeError(__former_attrs__[attr])
AttributeError: module 'numpy' has no attribute 'bool'.
`np.bool` was a deprecated alias for the builtin `bool`. To avoid this error in existing code, use `bool` by itself. ...
原因非常明确:mxnet 1.9.1 的代码中使用了 np.bool,这个别名在 numpy 1.20 起被标记弃用,在 numpy 1.24 中被彻底移除。注意报错位置是 mxnet/numpy/utils.py 第 37 行的模块级赋值语句,也就是说这不是使用某个特定功能才会触发的问题,而是 import 一发生就会失败。虽然 mxnet 自己声明只要求 numpy<2.0.0,但事实上 numpy 1.24 与它不兼容。解决办法是把 numpy 固定到 1.23.5(1.23 系列的最后一个补丁版本):
/opt/mxnet-env/bin/pip install "numpy==1.23.5"
一条经验总结:对于停止维护的老包,元数据声明的版本约束只能当作参考下限,真正可靠的依据是"实际能 import、能跑通"的实测结果。这也正是本文把 numpy 固定在 1.23.5 而不是放任 pip 自由解析的原因。
6.4 导入成功
第三次修复之后再次导入,实测成功:
/opt/mxnet-env/bin/python -c "import mxnet as mx; from mxnet import nd; print(\"mxnet\", mx.__version__); print(nd.array([[1,2],[3,4]]))"
输出:
mxnet 1.9.1
[[1. 2.]
[3. 4.]]
<NDArray 2x2 @cpu(0)>
至此安装完成。这个"装完即通"的假象到真正可用之间隔了三个坑,是所有 mxnet 1.9.1 安装者都会遇到的共性问题。
七、安装结果核验
7.1 查看包清单
/opt/mxnet-env/bin/pip list | grep -iE "mxnet|numpy"
实测输出:
mxnet 1.9.1
numpy 1.23.5
7.2 检查 wheel 兼容标记
如果要确认安装的是哪个分发文件,可以用 pip show:
/opt/mxnet-env/bin/pip show mxnet | head -5
输出中 Location 字段会指向 /opt/mxnet-env/lib/python3.8/site-packages,说明包确实装在虚拟环境内部,系统 Python 3.10 未受任何影响。
7.3 环境快照与一键重建
生产实践中常用"导出依赖清单 + 重装"的方式在不同服务器间复制同一套环境。先把当前环境的精确版本快照导出:
/opt/mxnet-env/bin/pip freeze > /opt/mxnet-requirements.txt
实测导出的清单内容如下(共 8 个包):
certifi==2026.7.22
charset-normalizer==3.5.2
graphviz==0.8.4
idna==3.15
mxnet==1.9.1
numpy==1.23.5
requests==2.32.4
urllib3==2.2.3
可以看到 mxnet 与 numpy 的版本已被精确钉住,其余为 requests 链上的间接依赖与 graphviz 绑定。在新机器上按同样步骤装好 Python 3.8 并创建 venv 后,一条命令即可复现整套环境:
/opt/mxnet-env/bin/pip install -r /opt/mxnet-requirements.txt
注意用 pip freeze 生成的清单包含所有间接依赖的精确版本号,复现能力最强;如果手工整理 requirements.txt,则至少要写明 mxnet==1.9.1 与 numpy==1.23.5 两条,避免 pip 自动解析到不兼容的 numpy。这种快照方式也天然规避了前文四连坑——因为 numpy 的版本已经被钉死在验证过的组合上。
7.4 GPU 可用性探测
无 GPU 的服务器上,以下探测语句是后续脚本的标准开头:
/opt/mxnet-env/bin/python -c "import mxnet as mx; print('available gpus:', mx.context.num_gpus())"
实测输出:
available gpus: 0
返回 0 表示当前只有 CPU 可用。对有 GPU 的机器,若返回值大于 0,还需要另行安装与驱动 CUDA 版本匹配的 mxnet-cuXXX 变体包,CPU 版 wheel 不能使用 GPU;反之 GPU 版包在无 GPU 机器上也无法运行,两者不可混装。
7.5 与其他软件的共存性检查
mxnet 1.9.1 落地前,建议确认服务器上没有其他 Python 项目会被这套环境影响。检查点有三个:其一,/opt/mxnet-env 是独立目录,对系统 Python 与其他 venv 零影响;其二,libgomp1 与 libquadmath0 属于增量补装的系统库,正常情况下只会增强兼容性,若服务器上有严格版本管控要求,用 apt-cache policy libgomp1 libquadmath0 核对安装来源是否为 Ubuntu 官方源;其三,若同一台服务器上还跑着其他深度学习框架(如 PyTorch、TensorFlow 的老版本),注意它们各自放在自己的 venv 里互不干扰即可,不要为了"统一"把不同框架装进同一个环境——这正是版本冲突最常见的来源。完成后建议把这组检查记录进运维台账,后续任何人接手都能快速理解这台服务器上的 Python 环境布局。
八、卸载与清理方法
8.1 卸载 mxnet 包
/opt/mxnet-env/bin/pip uninstall -y mxnet
实测输出:
Successfully uninstalled mxnet-1.9.1
若连带 numpy 一起清理,追加 pip uninstall -y numpy 即可。
8.2 彻底删除虚拟环境
venv 是一个自包含目录,直接删除即等于完全卸载:
sudo rm -rf /opt/mxnet-env
8.3 卸载系统级依赖(可选)
如果当初为了排障补装了系统库,且确认没有其他软件使用它们,可以一并卸载:
sudo apt-get remove -y libgomp1 libquadmath0
注意:libgomp1 在很多科学计算软件的依赖链上都会出现,卸载前建议用 apt-cache rdepends libgomp1 确认没有其他在用软件依赖它,一般保留不删更稳妥。
8.4 移除 Python 3.8(可选)
如果不再需要 Python 3.8:
sudo apt-get remove -y python3.8 python3.8-venv
sudo add-apt-repository -y --remove ppa:deadsnakes/ppa
8.5 离线安装方案(可选)
如果目标服务器完全无法访问外网,可以在一台能上网的同架构机器上先把 wheel 下载下来,再拷贝过去离线安装:
pip download mxnet==1.9.1 "numpy==1.23.5" -d /opt/mxnet-wheels
把 /opt/mxnet-wheels 目录整体传输到目标服务器后执行:
/opt/mxnet-env/bin/pip install --no-index --find-links=/opt/mxnet-wheels mxnet==1.9.1 "numpy==1.23.5"
--no-index 禁用在线索引,--find-links 指定本地 wheel 目录,pip 会只在目录内解析依赖。注意 download 必须在与目标服务器相同的操作系统与 Python 版本上进行(同为 Linux x86_64、同为 Python 3.8),否则解析出的 wheel 可能不匹配。离线方案同样绕不开 libgomp1 与 libquadmath0 两个系统库,需要用 apt 的离线包或本地源预先准备。
九、常见问题(FAQ)
1. Ubuntu 22.04 自带的 Python 3.10 能装 mxnet 1.9.1 吗? 不能。实测在 Python 3.10.12 下 pip 找不到匹配的 wheel(1.9.1 的 manylinux 包只提供到 Python 3.8/3.9 兼容级别),pip 会退回源码编译路径并失败。必须自建 Python 3.8 环境。
2. 除了 deadsnakes PPA,还有别的办法获得 Python 3.8 吗?
有。可以用 Miniconda/Anaconda 创建 py38 环境(conda create -n mxnet python=3.8),或者用 uv、pyenv 等版本管理工具安装。本文选择 PPA 方式是因为它对系统侵入最小、且 apt 生态与 Ubuntu 22.04 天然一致。选择任何一种方式,后续步骤完全相同。
3. pip install 报"externally-managed-environment"怎么办? 这是较新 pip 在系统 Python 上的保护机制。本文所有 pip 操作都发生在 /opt/mxnet-env 虚拟环境内部,不会触发该限制。如果你在系统 Python 上遇到它,正确做法同样是改用 venv,而不是加 --break-system-packages 强行绕过。
4. 安装完成后 import mxnet 报 OSError: libgomp.so.1 怎么处理?
安装 libgomp1:sudo apt-get install -y libgomp1。这是 MXNet 原生库对 OpenMP 运行时的硬依赖,缺它会在动态加载阶段直接失败。
5. 又报 OSError: libquadmath.so.0 怎么处理?
安装 libquadmath0:sudo apt-get install -y libquadmath0。与 libgomp 同理,都是 GCC 底层运行库。
6. 报 AttributeError: module 'numpy' has no attribute 'bool' 怎么处理?
把 numpy 降到 1.23.5:pip install "numpy==1.23.5"。mxnet 1.9.1 源码使用了 numpy 1.24 中已移除的 np.bool 别名,虽然它的元数据声明 numpy<2.0 即可,但实测 1.24.4 必然报错,1.23.5 是经实测验证可用的版本。
7. 为什么 pip 声明 numpy<2.0.0 却还会踩坑? mxnet 1.9.1 发布于 numpy 2.0 出现之前,其版本约束只考虑了"避免 numpy 2.0 的大破坏",但没有预料到 1.24 也会移除 np.bool 这类老别名。元数据约束与实际兼容性不完全一致,这是老包最常见的坑,遇到时以实测为准。
8. 安装时 apt 卡住不动怎么排查?
先用 ps aux | grep apt 查看是否有进程停留在 debconf/frontend 或某个 .config 脚本上。若有,说明卡在交互式配置(典型是 tzdata 时区配置)。终止该交互进程后,用 DEBIAN_FRONTEND=noninteractive dpkg --configure -a 补完配置即可。预防办法是安装时始终带上 DEBIAN_FRONTEND=noninteractive。
9. 下载 mxnet 的 49.1 MB wheel 太慢怎么办?
可以给 pip 配置国内镜像源(如 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple),或者为当前终端设置 HTTP 代理环境变量后再安装。两种方式实测均可行,本文回显中的下载地址即来自镜像源。
10. 装好后如何验证 mxnet 真的可用?
执行三步验证:导入并打印版本(import mxnet as mx; print(mx.__version__),应输出 1.9.1);创建并打印一个 NDArray(应有 <NDArray 2x2 @cpu(0)> 格式的输出);执行一次 nd.dot 矩阵乘法确认计算正常。三步都通过即可放心进入实战篇。
11. 需要单独安装 graphviz 吗?
看用途。pip 依赖解析时自动装上的 graphviz 是 Python 绑定包,仅供 import 使用;如果要把网络结构真正渲染成图片(mx.viz.plot_network 后调用 render),还需要系统级的 graphviz 工具:sudo apt-get install -y graphviz。只做训练与推理的话不需要这一步。
12. pip config 设置了国内镜像后,还能临时换回官方源吗?
可以。单次安装时加 -i https://pypi.org/simple 参数即可覆盖全局配置;反之,未配置镜像时也可以用 -i https://pypi.tuna.tsinghua.edu.cn/simple 临时走清华源。查看当前生效配置用 pip config list。镜像只影响下载速度,不影响包的版本与内容(镜像与官方源保持同步)。
十、参考链接
- PyPI 上的 mxnet 1.9.1 发布页:https://pypi.org/project/mxnet/1.9.1/
- deadsnakes PPA 主页:https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa
- Apache Attic 项目页(MXNet):https://attic.apache.org/projects/mxnet.html
- MXNet 归档官网安装文档:https://mxnet.apache.org/versions/1.9.1/get-started/
- numpy 1.20 发布说明(np.bool 弃用记录):https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
- numpy 1.23.5 发布页:https://pypi.org/project/numpy/1.23.5/
- Ubuntu 22.04 官方站点:https://releases.ubuntu.com/22.04/