# python-env-build **Repository Path**: fishorpalm/python-env-build ## Basic Information - **Project Name**: python-env-build - **Description**: Pyhton环境构建 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-26 - **Last Updated**: 2026-06-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # python-env-build 根据 `requirements.txt` 在 Docker 中用 **micromamba + conda-pack** 构建可离线分发的 Python 环境,支持指定目标架构(`amd64` / `arm64`)。 产物是**单个 `.tar.gz`**,顶层已附带 `activate.sh` 与 `README.md`。目标 Linux 机器上解压、跑一次 `conda-unpack`、`source bin/activate` 即可使用,**无需任何网络与 conda/pip**。 --- ## 适用场景 - 内网/离线服务器部署 Python 服务 - 边缘设备(树莓派、Jetson 等 ARM64 机器)分发预装环境 - CI 构建一次、批量下发到多台同架构机器 - 跨架构交叉打包(在 x86 开发机上为 ARM 服务器构建环境) --- ## 前置依赖 | 项 | 要求 | |----|------| | Docker | 已安装,daemon 正在运行 | | 跨架构支持 | Docker Desktop 自带 QEMU;Linux 宿主需执行一次 `docker run --privileged --rm tonistiigi/binfmt --install all` | | Shell | bash(Linux/macOS 原生;Windows 用 Git Bash 或 WSL) | 目标机器只需 `tar` + glibc 兼容的 Linux 即可,**不需要 Python、conda、pip**。 --- ## 快速开始 ```bash # 1. 准备 requirements.txt(仓库已带一个示例) cat requirements.txt # 2. 构建 ARM64 环境 ./build.sh --req requirements.txt --arch arm64 # 3. 查看产物(仅一个文件) ls dist/ # myenv-arm64.tar.gz ``` 把 `dist/myenv-arm64.tar.gz` 拷到目标 ARM64 Linux 机器,**在该 tarball 所在目录**执行: ```bash mkdir -p myenv tar -xzf myenv-arm64.tar.gz -C myenv # 解压后 myenv/ 顶层就能看到内嵌的 activate.sh 与 README.md myenv/activate.sh # 自动 conda-unpack 并打印激活命令 source myenv/bin/activate python -c "import sys; print(sys.version)" ``` --- ## CLI 参数 ``` ./build.sh --req --arch [选项] ``` | 参数 | 必填 | 默认值 | 说明 | |------|------|--------|------| | `--req ` | 是 | — | requirements.txt 路径 | | `--arch ` | 是 | — | 目标架构 | | `--python ` | 否 | `3.11` | Python 版本 | | `--name ` | 否 | `myenv` | 环境名(仅含字母/数字/`_`/`-`) | | `--output ` | 否 | `./dist` | 产物输出目录 | | `--image ` | 否 | `mambaorg/micromamba:1.5.10` | micromamba 基础镜像(已固定 tag 保证可重现) | | `--pip-index ` | 否 | 清华 TUNA | pip 索引源 | | `--conda-channel ` | 否 | 清华 conda-forge | conda channel | | `-h, --help` | — | — | 帮助 | ### 常见组合 ```bash # 给 x86 Linux 服务器打包,Python 3.10 ./build.sh --req requirements.txt --arch amd64 --python 3.10 # 自定义环境名和输出目录 ./build.sh --req requirements.txt --arch arm64 --name svc-runtime --output ./build # 切换到阿里源 ./build.sh --req requirements.txt --arch arm64 \ --pip-index https://mirrors.aliyun.com/pypi/simple/ # 同一份 requirements 同时打两个架构(跑两次) ./build.sh --req requirements.txt --arch amd64 ./build.sh --req requirements.txt --arch arm64 ``` --- ## 工作原理 ``` ┌─────────────────────────── 宿主机 ──────────────────────────┐ │ │ │ build.sh │ │ │ │ │ │ 写 activate.sh / README.md 到 staging │ │ │ docker run --platform linux/ │ │ ▼ │ │ ┌──────────────────── 容器 (mambaorg/micromamba) ────────┐ │ │ │ │ │ │ │ micromamba create -n myenv -c <清华 conda-forge> │ │ │ │ python= pip conda-pack │ │ │ │ │ │ │ │ micromamba run -n myenv pip install -r req.txt │ │ │ │ --index-url <清华 PyPI> │ │ │ │ │ │ │ │ conda-pack --format tar → /tmp/myenv.tar │ │ │ │ tar -rf myenv.tar activate.sh README.md │ │ │ │ gzip -6 → /out/myenv-.tar.gz │ │ │ └────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ (挂载卷写出) │ │ dist/ │ │ myenv-.tar.gz ← 顶层含 activate.sh + README.md │ │ │ └──────────────────────────────────────────────────────────────┘ ``` 跨架构靠 Docker 的 `--platform` 与宿主上的 QEMU/binfmt 转译,不依赖 buildx。 --- ## 目标机器使用 下面所有命令默认你已经把 `myenv-.tar.gz` 拷到目标机器并 `cd` 到该文件所在目录,环境就解压到当前目录的 `myenv/` 子目录。**想换位置就把 `myenv` 换成 `/opt/myenv`、`~/envs/myenv` 等任意路径**(绝对路径需要相应权限)。 ```bash mkdir -p myenv tar -xzf myenv-.tar.gz -C myenv ``` 解压后顶层结构(节选): ``` myenv/ ├── bin/ # python、pip、conda-unpack 等 ├── lib/ ├── etc/ ├── activate.sh # ← 内嵌的一键脚本 └── README.md # ← 内嵌的使用说明 ``` ### 一键 ```bash myenv/activate.sh # 自动 conda-unpack 并打印激活提示 source myenv/bin/activate ``` ### 手动 ```bash # 用环境内的 python 显式调用 conda-unpack myenv/bin/python myenv/bin/conda-unpack source myenv/bin/activate ``` > **`conda-unpack` 是关键一步**:conda-pack 打包时把绝对路径替换成占位符,解压后必须运行 `conda-unpack` 才能让二进制中的 shebang / rpath 指向正确位置。 > > **不要直接跑 `bin/conda-unpack`**:它的 shebang 是 `#!/usr/bin/env python`,如果目标机的系统 `python` 命令是 Python 2.x 或 < 3.6(很多 CentOS / 老 Ubuntu 都是),会撞到 f-string 的 `SyntaxError`。用 `bin/python bin/conda-unpack` 显式调用环境内的 Python 即可绕过。 ### 不激活直接调用(推荐服务/脚本部署) 跑过一次 `conda-unpack` 后,环境内的可执行文件可以**直接用绝对路径调用**,无需 `source activate`: ```bash myenv/bin/python xx.py myenv/bin/pip list myenv/bin/uvicorn app:app --host 0.0.0.0 --port 8000 ``` 部署到 systemd / Docker 时通常会把环境放在固定位置(如 `/opt/myenv`),命令也相应改成绝对路径: ```ini # systemd unit(按你的实际部署位置改) [Service] ExecStart=/opt/myenv/bin/python /app/main.py ``` ```dockerfile # Dockerfile(按你的实际部署位置改) CMD ["/opt/myenv/bin/python", "main.py"] ``` #### 什么时候必须 `source activate`? `source activate` 做三件事,对运行脚本而言:把 `bin/` 加进 `PATH`(无用)、设置 `CONDA_*` 变量(无用)、**执行 `etc/conda/activate.d/*.sh` 钩子**(可能有用)。 只有少数 **conda 安装**(注意:不是 pip 安装)的包会注册钩子来设置运行时环境变量,常见的有: | 包 | 钩子设置的变量 | 不设置的后果 | |----|--------------|------------| | `gdal` / `proj` | `GDAL_DATA`、`PROJ_LIB` | 找不到坐标系/投影数据 | | `cudatoolkit` | `LD_LIBRARY_PATH`、`CUDA_HOME` | 找不到 CUDA 动态库 | | `pyqt` / `qt` | `QT_PLUGIN_PATH` | Qt 插件加载失败 | | 部分 `openssl` | `SSL_CERT_FILE` | TLS 证书校验失败 | **自查命令**(在目标机器上): ```bash ls myenv/etc/conda/activate.d/ 2>/dev/null ``` - 目录不存在 / 为空 → 直接调用绝对路径完全 OK - 有 `.sh` 文件 → 看里面 `export` 了什么;要么 `source activate`,要么在 systemd 的 `Environment=` 里手动 export 同样变量 > 纯 pip 安装的 requirements 不会写 `activate.d` 钩子,绝对路径调用总是 OK。 --- ## 常见问题 **Q: 在 macOS / Windows 上能直接解压使用产物吗?** 不能。conda-pack 产物绑定构建平台 Linux + 指定架构,二进制无法在其他系统运行。开发调试请直接在本机用 venv/conda。 **Q: 打 ARM64 但宿主是 x86,构建很慢?** 正常。QEMU 软件模拟跨架构指令,编译/解包步骤会比原生慢数倍。建议尽量用 wheel 包,少用源码包。 **Q: `requirements.txt` 里有需要 C/C++ 编译的源码包,构建失败?** `mambaorg/micromamba` 镜像没装 gcc/g++。优先把对应包改为预编译 wheel;或在脚本里加 `apt-get install -y build-essential` 自定义(脚本暂未透传 `--apt-packages`,需要时直接改容器内部分)。 **Q: 公司有私有 PyPI 镜像?** 用 `--pip-index <你的镜像>` 即可,脚本会自动从 URL 提取 host 设为 `--trusted-host`。 **Q: 想换 micromamba 版本?** 默认已固定到 `mambaorg/micromamba:1.5.10`,避免 `latest` 漂移导致的构建结果不稳定。换版本传 `--image mambaorg/micromamba:`。 **Q: 跑 `bin/conda-unpack` 时报 `SyntaxError: invalid syntax`(f-string 那行)?** 目标机的系统 `python` 命令版本太低(< 3.6),而 `conda-unpack` 的 shebang `#!/usr/bin/env python` 找到了它。改用环境内 Python 显式调用: ```bash /bin/python /bin/conda-unpack ``` 内嵌的 `activate.sh` 已经是这么做的,遇到这个错说明用户直接跑了 `bin/conda-unpack`。 **Q: 产物体积偏大?** conda-pack 默认级别 6 已是性价比较好的压缩。若需进一步减小: - 精简 `requirements.txt`(去掉非必要依赖) - 用 `pip install --no-deps` 思路自己控制依赖树(需要修改脚本) - 解压后删 `**/__pycache__`、`**/tests` 再重新压缩 --- ## 仓库结构 ``` python-env-build/ ├── build.sh # 主脚本 ├── requirements.txt # 示例 requirements ├── README.md # 本文件 └── dist/ # 构建产物(首次运行后生成) ```