离线 Python 环境部署流程文档
deploy_pkg 构建流程
1.1 目标
构建一个可在现场离线使用的 Python 环境包,包含:
northland_deploy_pkg/ ├── bin/ │ └── uv ├── python/ │ └── Python 3.10.0 ├── wheelhouse/ │ └── 离线依赖 wheel 包 ├── requirements.lock.txt ├── install.sh └── run_env.sh
说明:
| 目录/文件 | 作用 |
| bin/uv | uv 可执行文件,用于创建虚拟环境和安装依赖 |
| python/ | 随包携带的 Python 3.10.0 |
| wheelhouse/ | 提前下载好的离线依赖包 |
| requirements.lock.txt | 固定版本后的依赖清单 |
| install.sh | 现场离线安装脚本 |
| run_env.sh | 现场激活虚拟环境脚本 |
1.2 构建环境要求
构建环境需要和现场机器架构一致。
在构建机器执行:
uname -m
命令说明:
| 命令 | 说明 |
| uname -m | 查看 CPU 架构 |
RK3568 通常应输出:
aarch64
如果输出是x86_64,则不能直接用于 RK3568 现场部署包构建。
1.3 创建 deploy_pkg 目录
mkdir -p /northland_deploy_pkg/{bin,python,wheelhouse} cd /northland_deploy_pkg
命令说明:
| 命令 | 说明 |
| bin | 存放 uv |
| python | 存放 Python 3.10.0 |
| wheelhouse | 存放离线依赖包 |
1.4 安装并复制 uv
curl -LsSf https://astral.sh/uv/install.sh | sh
命令说明:
| 命令 | 说明 |
| curl -LsSf ... | 下载 uv 安装脚本 |
| sh | 执行安装脚本 |
检查 uv:
which uv uv --version
复制 uv 到部署包:
cp "$(which uv)" ./bin/uv chmod +x ./bin/uv
1.5 安装 Python 3.10.0
要求 Python 版本必须是3.10.0,不要只写3.10。
export UV_PYTHON_INSTALL_DIR="$PWD/python" ./bin/uv python install 3.10.0
命令说明:
| 命令 | 说明 |
| export UV_PYTHON_INSTALL_DIR="$PWD/python" | 指定 Python 安装到当前部署包的 python/ 目录 |
| ./bin/uv python install 3.10.0 | 安装精确版本 Python 3.10.0 |
查找 Python:
PY310=$(find "$PWD/python" -type f -name "python3.10" | head -n 1) echo "$PY310" "$PY310" --version
1.6 创建构建用虚拟环境
./bin/uv venv .venv --python "$PY310" --no-python-downloads --seed
命令说明:
| 命令 | 说明 |
| uv venv .venv | 创建虚拟环境 |
| --python "$PY310" | 使用部署包内的 Python 3.10.0 |
| --no-python-downloads | 禁止 uv 自动下载其他 Python |
| --seed | 创建虚拟环境时安装 pip、setuptools、wheel 等基础工具 |
检查版本:
.venv/bin/python --version .venv/bin/python -m pip --version
1.7 安装依赖
将项目的requirements.txt放到:
/northland_deploy_pkg/requirements.txt
执行:
./bin/uv pip install --python .venv/bin/python -r requirements.txt
如果需要安装开发依赖:
./bin/uv pip install --python .venv/bin/python -r requirements-dev.txt
1.8 生成锁定依赖文件
./bin/uv pip freeze --python .venv/bin/python > requirements.lock.txt
命令说明:
| 命令 | 说明 |
| uv pip freeze | 输出当前虚拟环境中的完整依赖版本 |
| > requirements.lock.txt | 保存为固定版本依赖清单 |
检查依赖冲突:
./bin/uv pip check --python .venv/bin/python
1.9 下载离线依赖包
.venv/bin/python -m pip download -r requirements.lock.txt -d wheelhouse
命令说明:
| 命令 | 说明 |
| pip download | 只下载依赖包,不安装 |
| -r requirements.lock.txt | 按固定版本下载依赖 |
| -d wheelhouse | 将依赖包保存到 wheelhouse/ 目录 |
1.10 处理源码包
检查wheelhouse中是否还有源码包:
find wheelhouse -maxdepth 1 \( -name "*.tar.gz" -o -name "*.zip" \) -print
命令说明:
| 命令 | 说明 |
| find wheelhouse | 查找 wheelhouse 中的文件 |
| *.tar.gz / *.zip | 源码包格式 |
| 没有输出 | 表示依赖包都是 wheel,适合离线安装 |
如果存在源码包,需要提前构建 wheel,例如:
.venv/bin/python -m pip wheel --no-deps --no-build-isolation -w wheelhouse wheelhouse/psutil-5.9.8.tar.gz
命令说明:
| 命令 | 说明 |
| pip wheel | 将源码包构建成 wheel |
| --no-deps | 不额外解析依赖 |
| --no-build-isolation | 不创建隔离构建环境 |
| -w wheelhouse | 将生成的 wheel 放回 wheelhouse |
构建成功后删除源码包:
rm -f wheelhouse/*.tar.gz wheelhouse/*.zip
再次检查:
find wheelhouse -maxdepth 1 \( -name "*.tar.gz" -o -name "*.zip" \) -print
如果无输出,说明处理完成。
1.11 本机离线模拟安装
创建测试环境:
UV_OFFLINE=1 ./bin/uv venv .venv_test --python "$PY310" --no-python-downloads --seed
离线安装依赖:
UV_OFFLINE=1 ./bin/uv pip sync requirements.lock.txt --python .venv_test/bin/python \ --no-index \ --find-links wheelhouse \ --offline
命令说明:
| 命令 | 说明 |
| UV_OFFLINE=1 | 强制 uv 离线运行 |
| uv pip sync | 按 lock 文件同步安装依赖 |
| --no-index | 不访问 PyPI |
| --find-links wheelhouse | 只从本地 wheelhouse 查找依赖 |
| --offline | 禁止联网 |
检查依赖:
./bin/uv pip check --python .venv_test/bin/python
测试核心依赖导入:
.venv_test/bin/python - <<'PY' import numpy import pandas import sklearn import scipy import torch import psutil import gflags print("offline dependency test ok") PY
测试完成后删除测试环境:
rm -rf .venv_test
1.12 编写 install.sh
在/northland_deploy_pkg/install.sh中写入:
#!/usr/bin/env bash set -euo pipefail BASE="$(cd "$(dirname "$0")" && pwd)" UV="$BASE/bin/uv" export UV_OFFLINE=1 export UV_LINK_MODE=copy PYTHON="$(find "$BASE/python" -type f -name "python3.10" | head -n 1)" if [ -z "$PYTHON" ]; then echo "ERROR: cannot find bundled python3.10" exit 1 fi echo "Using Python: $PYTHON" "$PYTHON" --version "$PYTHON" - <<'PY' import sys if sys.version_info[:3] != (3, 10, 0): raise SystemExit(f"ERROR: Python version must be 3.10.0, current: {sys.version}") print("Python version check passed") PY "$UV" venv "$BASE/.venv" \ --python "$PYTHON" \ --no-python-downloads \ "$UV" pip sync "$BASE/requirements.lock.txt" \ --python "$BASE/.venv/bin/python" \ --no-index \ --find-links "$BASE/wheelhouse" \ --offline "$UV" pip check \ --python "$BASE/.venv/bin/python" echo "Install finished." echo "Activate with:" echo "source $BASE/.venv/bin/activate"
添加执行权限:
chmod +x install.sh
脚本说明:
| 内容 | 说明 |
| set -euo pipefail | 遇到错误立即退出 |
| BASE=... | 获取 install.sh 所在目录 |
| UV="$BASE/bin/uv" | 使用部署包内的 uv |
| UV_OFFLINE=1 | 强制离线 |
| UV_LINK_MODE=copy | 使用复制模式,避免硬链接问题 |
| find "$BASE/python" | 查找随包携带的 Python |
| sys.version_info[:3] != (3, 10, 0) | 严格校验 Python 必须是 3.10.0 |
| uv venv "$BASE/.venv" | 创建现场虚拟环境 |
| uv pip sync | 从本地 wheelhouse 安装依赖 |
| uv pip check | 检查依赖冲突 |
1.13 编写 run_env.sh
在/northland_deploy_pkg/run_env.sh中写入:
#!/usr/bin/env bash BASE="$(cd "$(dirname "$0")" && pwd)" source "$BASE/.venv/bin/activate" echo "Virtual environment activated:" which python python --version
添加执行权限:
chmod +x run_env.sh
脚本说明:
| 内容 | 说明 |
| source "$BASE/.venv/bin/activate" | 激活部署包中的虚拟环境 |
| which python | 查看当前使用的 Python |
| python --version | 确认 Python 版本 |
1.14 打包 deploy_pkg
打包前确认必要文件:
cd /northland_deploy_pkg ls bin/uv find python -type f -name "python3.10" ls requirements.lock.txt ls install.sh run_env.sh find wheelhouse -maxdepth 1 -name "*.whl" | wc -l find wheelhouse -maxdepth 1 \( -name "*.tar.gz" -o -name "*.zip" \) -print
要求:
| 检查项 | 要求 |
| bin/uv | 必须存在 |
| python3.10 | 必须存在 |
| requirements.lock.txt | 必须存在 |
| install.sh | 必须存在 |
| run_env.sh | 必须存在 |
| wheelhouse/*.whl | 必须存在 |
| *.tar.gz / *.zip | 最好没有输出 |
打包:
# 返回northland_deploy_pkg的上一级 cd .. tar -zcvf northland_deploy_pkg.tar.gz \ --exclude='northland_deploy_pkg/.venv' \ --exclude='northland_deploy_pkg/.venv_test' \ --exclude='northland_deploy_pkg/.cache' \ --exclude='northland_deploy_pkg/__pycache__' \ northland_deploy_pkg
命令说明:
| 命令 | 说明 |
| cd / | 进入根目录,保证打包路径一致 |
| tar -zcvf | 使用 gzip 压缩打包 |
| --exclude='.venv' | 不打包构建用虚拟环境 |
| --exclude='.venv_test' | 不打包测试虚拟环境 |
| --exclude='.cache' | 不打包缓存 |
| northland_deploy_pkg | 需要打包的目录 |
deploy_pkg 现场应用流程
2.1 现场目录规划
假设现场算法代码目录为:
/znv/newland/backendpackage/Northland-O_V2.10.001_20260513
部署包建议解压到同级目录:
/znv/newland/backendpackage/northland_deploy_pkg
最终结构:
/znv/newland/backendpackage/ ├── Northland-O_V2.10.001_20260513/ │ └── 现场算法代码 └── northland_deploy_pkg/ ├── bin/ ├── python/ ├── wheelhouse/ ├── requirements.lock.txt ├── install.sh └── run_env.sh
说明:
| 目录 | 说明 |
| Northland-O_V2.10.001_20260513 | 原有算法代码目录 |
| northland_deploy_pkg | 离线 Python 环境包 |
| .venv | 执行 install.sh 后生成的虚拟环境 |
2.2 上传部署包
将以下文件上传到现场服务器/tmp:
northland_deploy_pkg.tar.gz
2.3 解压部署包
tar -zxvf northland_deploy_pkg.tar.gz -C /znv/newland/backendpackage
解压后确认:
ls /znv/newland/backendpackage/northland_deploy_pkg
应能看到:
bin python wheelhouse requirements.lock.txt install.sh run_env.sh
2.4 执行 install.sh
进入部署包目录:
cd /znv/newland/backendpackage/northland_deploy_pkg
执行安装:
chmod +x install.sh ./install.sh
命令说明:
| 命令 | 说明 |
| cd .../northland_deploy_pkg | 进入部署包目录 |
| chmod +x install.sh | 给安装脚本添加执行权限 |
| ./install.sh | 创建 .venv 并离线安装依赖 |
安装成功后会生成:
/znv/newland/backendpackage/northland_deploy_pkg/.venv
2.5 激活虚拟环境
执行run_env.sh激活虚拟环境
. run_env.sh
检查当前 Python:
which python python --version
期望结果:
/znv/newland/backendpackage/northland_deploy_pkg/.venv/bin/python Python 3.10.0
2.6 检查依赖
如果当前 shell 已经激活.venv,可以执行:
python -m pip check
测试核心依赖:
python - <<'PY' import numpy import pandas import sklearn import scipy import torch import psutil import gflags print("dependency ok") PY
2.7 运行现场算法
激活虚拟环境后,进入算法目录:
cd /znv/newland/backendpackage/Northland-O_V2.10.001_20260513
然后按原有方式执行算法即可。
如果原有启动命令是 shell 脚本,例如:
./start.sh
则执行:
source /znv/newland/backendpackage/northland_deploy_pkg/.venv/bin/activate cd /znv/newland/backendpackage/Northland-O_V2.10.001_20260513 ./start.sh
注意:如果start.sh中写死了/usr/bin/python3,则不会使用虚拟环境 Python;需要将启动脚本中的 Python 命令改成python,或在启动脚本前显式激活虚拟环境。
2.9 退出虚拟环境
deactivate
