AI 写文章系列——Ubuntu 24.04 pipx install 解决 ModuleNotFoundError 问题

概述

自从转 Go 之后,好久没写 Python 了。最近在 Ubuntu 24.04 中使用 pipx 安装了一个工具之后,运行报依赖错误。把上下文喂给 DeepSeek 之后,最终解决了问题。

我让 DeepSeek 回顾问答的上下文,整理了一篇文章出来——不过相比上一篇,这次我人工介入修改的内容多得多。


问题提出

最近需要扣一个图,把我的证件照背景颜色换一换。搜了一下,在 Github 上找到一个高 star 的项目 rembg 的图片背景去除工具,用 pipx install rembg 安装后运行时,却遇到了 ModuleNotFoundError: No module named 'onnxruntime' 的错误。这明显是包依赖问题。奇怪了,看起来 pipx 没有 pip 那么聪明?

为什么用 pipx 而不是 pip?

在 Ubuntu 24.04 中,系统默认安装了 Python 3.12,所以我就不用费心去自己通过源码安装。但为了避免污染全局环境,官方不推荐使用 pip,而是 pipx 来管理命令行工具。原因如下:

  • 系统 Python 的自我保护: Ubuntu 的系统工具(如 apt)依赖 Python 环境,直接使用 pip 安装全局包可能导致依赖冲突,甚至破坏系统功能。
  • 隔离性需求: pipx 会为每个包创建独立的虚拟环境,避免包之间的依赖冲突。例如,安装 rembg 时,其依赖的 numpy 版本不会影响其他工具。
  • 命令行工具的天然适配: pipx 会自动将包的可执行文件链接到 ~/.local/bin,无需手动配置环境变量,适合管理 rembg 这类 CLI 工具。

现象

安装 rembg 看似成功,但运行时直接报错:

代码语言:bash复制
$ rembg i input.png output.png
Traceback (most recent call last):
  File "/root/.local/bin/rembg", line 5, in <module>
    from rembg.cli import main
  File "/root/.local/share/pipx/venvs/rembg/lib/python3.12/site-packages/rembg/__init__.py", line 5, in <module>
    from .bg import remove
  File "/root/.local/share/pipx/venvs/rembg/lib/python3.12/site-packages/rembg/bg.py", line 7, in <module>
    import onnxruntime as ort
ModuleNotFoundError: No module named 'onnxruntime'

关键信息: rembg 运行时找不到 onnxruntime 模块。


解决方案

找 DeepSeek 问,说实话,DeepSeek 对问题的原因的解释并不能让我满意,它给出的解决方法也有好几条。经过 7 轮问答,我最终挑选了一个可行的方案。

被验证不可行的方案

  1. 强制重装 rembg

尝试卸载后强制重装,但问题依旧:

代码语言:bash复制
pipx uninstall rembg
pipx install rembg --force
  1. 全局安装 onnxruntime

直接运行 pipx install onnxruntime,这个方法可以,但是依赖又不止这一个,一个个安装挺麻烦的。此外 pipx install 会为 onnxruntime 创建新虚拟环境,而非注入到 rembg 的环境,推荐用 pipx inject 的模式。


关键操作: pipx inject vs pipx install

1. pipx inject 的作用
  • 精准注入依赖: 将指定包安装到某个应用的虚拟环境中。
  • 解决依赖隔离问题: 例如,为 rembg 单独安装 onnxruntime:
代码语言:bash复制
pipx inject rembg onnxruntime

最终解决方案: 自动化脚本

  1. 自动捕获缺失依赖: 从错误日志中提取 ModuleNotFoundError 提示的模块名。
  2. 循环安装与重试: 直到命令成功或达到最大重试次数。
代码语言:bash复制
#!/bin/bash
# auto_fix_pipx_deps_loop_fixed.sh

# 配置参数
PACKAGE="rembg"  # 替换为你的包名
COMMAND="rembg"  # 替换为需要执行的命令
MAX_RETRY=20     # 最大重试次数,防止无限循环

# 临时日志文件
LOG="/tmp/pipx_error.log"

# 初始化计数器
retry_count=0
success=0

while [ $retry_count -lt $MAX_RETRY ] && [ $success -eq 0 ]; do
    # 清理旧日志
    rm -f "$LOG"

    # 运行命令并捕获输出,同时记录原始退出状态码
    echo "尝试运行命令 (第 $((retry_count+1)) 次)..."
    $COMMAND 2>&1 | tee "$LOG"
    original_exit_code=${PIPESTATUS[0]}  # 获取原命令的退出状态码

    # 检查命令是否成功
    if [ $original_exit_code -eq 0 ]; then
        echo "命令执行成功!"
        success=1
        break
    else
        echo "命令执行失败,退出码: $original_exit_code"
    fi

    # 提取缺失的模块名(去重)
    MISSING_MODULES=$(grep -o "ModuleNotFoundError: No module named '[^']*'" "$LOG" | awk -F"'" '{print $2}' | sort | uniq)

    if [ ! -z "$MISSING_MODULES" ]; then
        echo "检测到缺失依赖: $MISSING_MODULES"
        for MODULE in $MISSING_MODULES; do
            echo "正在安装: $MODULE"
            pipx inject "$PACKAGE" "$MODULE"
            if [ $? -ne 0 ]; then
                echo "安装依赖 $MODULE 失败,请手动处理。"
                exit 1
            fi
        done
    else
        echo "未检测到缺失的 Python 依赖。请检查以下可能原因:"
        echo "1. 系统级依赖未安装(如 libgomp1)"
        echo "2. 动态导入的依赖未在代码中显式声明"
        echo "3. 其他运行时错误(查看日志: $LOG)"
        break
    fi

    # 增加重试计数
    retry_count=$((retry_count+1))
done

# 最终状态检查
if [ $success -eq 0 ]; then
    echo "已达到最大重试次数 ($MAX_RETRY),问题仍未解决。请手动检查日志: $LOG"
    exit 1
else
    exit 0
fi
脚本运行效果

执行效果类似于这样子的:

代码语言:txt复制
尝试运行命令 (第 1 次)...
Traceback (most recent call last):
  File "/root/.local/bin/rembg", line 5, in <module>
    from rembg.cli import main
ModuleNotFoundError: No module named 'onnxruntime'
检测到缺失依赖: onnxruntime
正在安装: onnxruntime
  injected package onnxruntime into venv rembg

尝试运行命令 (第 2 次)...
Traceback (most recent call last):
  File "/root/.local/bin/rembg", line 5, in <module>
    from rembg.cli import main
  File "/root/.local/share/pipx/venvs/rembg/lib/python3.12/site-packages/rembg/cli.py", line 4, in <module>
    from mands import command_functions
  File "/root/.local/share/pipx/venvs/rembg/lib/python3.12/site-packages/rembg/commands/__init__.py", line 7, in <module>
    from .s_command import s_command
  File "/root/.local/share/pipx/venvs/rembg/lib/python3.12/site-packages/rembg/commands/s_command.py", line 6, in <module>
    import aiohttp
ModuleNotFoundError: No module named 'aiohttp'
命令执行失败,退出码: 1
检测到缺失依赖: aiohttp
正在安装: aiohttp
  injected package aiohttp into venv rembg

......

安装过程中会出现一些失败的情况,一般都是超时等网络问题。解决网络错误之后再跑这个脚本就行了


本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

原作者: amc,欢迎转载,但请注明出处。

原文标题: 《AI 写文章系列——Ubuntu 24.04 pipx install 解决 ModuleNotFoundError 问题》

发布日期: 2025-03-29

原文链接: 。

CC BY-NC-SA 4.0 DEED.png