我们公司的产品中使用了两个版本的 Python,其中 2.7.15 版本是历史原因遗留的,而另一个版本是 3.12.x,但是我在运行新装的 3.12 版本的时候会出现报错找不到 libpython3.12.so.1.0 文件。经过向 AI 咨询问题产生的原因和解决方案,我整理了这个博客,来记录一下遇到这种问题,在不同场景下的解决方案。

问题描述

在 Linux 系统上,编译安装 Python 之后,运行时可能会遇到以下错误:

./python3: error while loading shared libraries: libpython3.12.so.1.0: cannot open shared object file: No such file or directory

这个问题的根本原因是 Python 可执行文件找不到 libpython3.x.so.1.0 共享库,导致运行失败。这个问题在 多个 Python 版本安装在不同目录 的环境中更为突出。常见的安装路径包括:

  • /usr/local/python3.12/
  • /opt/python3.10/
  • /usr/local/python3.9/

由于这些 Python 版本的 libpython3.x.so.1.0 库文件路径各不相同,系统的 动态链接器(ld) 无法自动找到正确的库文件,导致 Python 无法运行。

常见的解决方案

方案 1:使用 ldconfig(适用于单一 Python 版本)

如果系统只有 一个主要的 Python 版本,可以手动将 libpython3.x.so.1.0 添加到动态库搜索路径:

echo "/usr/local/python3.12/lib" | sudo tee /etc/ld.so.conf.d/python3.12.conf
sudo ldconfig

然后验证库是否已正确注册:

ldconfig -p | grep libpython

缺点

  • 如果有多个 Python 版本,可能会导致动态库冲突。
  • 不能保证每个 Python 版本都能正确找到自己的 libpython3.x.so.1.0

方案 2:使用 LD_LIBRARY_PATH(适用于手动切换 Python)

另一种常见的方法是 在运行 Python 前手动指定 LD_LIBRARY_PATH

export LD_LIBRARY_PATH=/usr/local/python3.12/lib:$LD_LIBRARY_PATH
/usr/local/python3.12/bin/python3.12

如果希望 每次自动生效,可以将这行命令添加到 ~/.bashrc

echo 'export LD_LIBRARY_PATH=/usr/local/python3.12/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc

缺点

  • 每次切换 Python 版本时都需要手动修改 LD_LIBRARY_PATH
  • 影响当前终端 session,不适用于长期维护多个 Python 版本的环境。

最佳解决方案:使用 RPATH

适用于多个 Python 版本共存,每个 Python 版本独立运行,不影响其他版本。

为什么选择 RPATH?

  • 每个 Python 版本可以自己找到自己的 libpython3.x.so.1.0,不会相互干扰。
  • 不需要手动 export LD_LIBRARY_PATH,运行时自动找到库文件。
  • 不会影响系统的全局 ldconfig 配置,避免潜在的库冲突。

如何使用 RPATH 解决问题?

1️⃣ 确认 libpython3.x.so.1.0 的位置

find /usr/local/python3.12 -name "libpython3.12.so.1.0"

假设输出:

/usr/local/python3.12/lib/libpython3.12.so.1.0

2️⃣ 修改 Python 可执行文件的 RPATH

patchelf --set-rpath /usr/local/python3.12/lib /usr/local/python3.12/bin/python3.12

⚠️ 如果 patchelf 未安装,可以使用以下命令安装:

# Ubuntu/Debian
sudo apt install patchelf
# CentOS/Fedora
sudo yum install patchelf

3️⃣ 验证 RPATH 是否生效

ldd /usr/local/python3.12/bin/python3.12 | grep libpython

如果输出:

libpython3.12.so.1.0 => /usr/local/python3.12/lib/libpython3.12.so.1.0

说明 Python 已正确找到 libpython3.12.so.1.0,问题解决! 🎉


总结

方案 适用场景 是否永久 适用多个 Python 隔离性 复杂度
方案 1:使用 ldconfig 只有一个 Python 版本 ✅ 是 ⚠ 可能有冲突 ❌ 低隔离
方案 2:使用 LD_LIBRARY_PATH 需要手动切换 Python 版本 ❌ 否 ✅ 支持 ✅ 高隔离 ⭐⭐
方案 3:使用 RPATH 多个 Python 版本共存 ✅ 是 ✅ 支持 ✅ 高隔离 ⭐⭐⭐

👉 最终选择RPATH ✅,它能够让每个 Python 版本自己找到自己的 libpythonX.Y.so.1.0,避免冲突,实现真正的独立运行。 🚀