已编译 python 版本:导入时出现 ModuleNotFoundError

Compiled python version: ModuleNotFoundError at import

我在 conda 环境中有一个项目 运行 使用 python 3.7.7(在 linux 上)。当我在同一位置重新编译相同版本的 python (3.7.7) 和 put/replace 可执行文件时,我希望程序以相同的方式 运行,但导入失败。

与原版python:

(condaenv) mypc:~/Proj$ /home/me/.conda/envs/condaenv/bin/python3.7.bak
Python 3.7.7 (default, Mar 26 2020, 15:48:22) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import gym
>>> quit()

编译版本:

(condaenv) mypc:~/Proj$ /home/me/.conda/condaenv/proj/bin/python3.7
Python 3.7.7 (default, Sep 24 2020, 16:28:06) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import gym
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'gym'
>>> quit()

环境变量应该与我 运行 在同一位置、同一终端上的环境变量相同,并且不会在两次调用之间进行更改。由于第一次导入没有任何问题,所以安装包很好。

sys 等系统导入在两个版本中都可以正常工作,但我必须在编译版本之前导出 LD_LIBRARY_PATH,而“普通”版本则不是这样。但是在两次调用之间保持 LD_LIBRARY_PATH 不变不会改变任何东西。

第二次调用找不到匹配的包怎么办?我错过了什么?

-- 编辑 1 --

编译后的版本共享对象依赖如下:

$ ldd python3.7
        linux-vdso.so.1 (0x00007ffed457a000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f63e53a6000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f63e53a0000)
        libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f63e539b000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f63e524c000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f63e505a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f63e577f000)

原文python如下:

$ ldd python3.7.bak 
        linux-vdso.so.1 (0x00007ffc0d1c8000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f89ab6bc000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f89ab4ca000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f89ab4c4000)
        libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f89ab4bf000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f89ab4b4000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f89ab365000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f89aba80000)

版本略有不同,因为它们不是使用相同版本的编译器编译的(我猜)。然而,令我惊讶的是新版本不需要 librt.so 但原始版本需要。可能是因为编译标志阻止了优化。我在配置步骤中添加了 --without-pymalloc --with-pydebug --with-valgrind。但我认为它不应该干扰 python 库的正常行为。

你在哪里编译了新的Python?可能是缺少 lib librt.so.1 是错误消息的罪魁祸首。有没有机会安装 librt 包(取决于你的 Linux 风格)并重新编译 Python.

--without-pymalloc--with-pydebug 标志到 ./configure 可能导致错误。用 ./configure --without-pymalloc./configure --with-pydebug 构建的二进制文件替换 miniconda 中的 python3.7 二进制文件可防止导入已编译的库,如 mathnumpy。没有任何标志(即 ./configure && make)的编译不会导致这些错误。使用 ./configure --with-valgrind 编译在导入已编译的库时也不会引发错误。


较早的回答:

你能试试 configure flags used by conda-forge 吗?使用这些标志,我能够在 conda 环境中替换 python3.7 二进制文件,并且导入继续工作。如果我使用 OP 的标志(即 --without-pymalloc --with-pydebug --with-valgrind),则导入编译库不起作用(例如 math、numpy)。

curl -L https://www.python.org/ftp/python/3.7.7/Python-3.7.7.tar.xz | tar xJ
cd Python-3.7.7
./configure \
    --prefix=/tmp/python3.7 \
    --enable-ipv6 \
    --with-ensurepip=no \
    --with-computed-gotos \
    --with-system-ffi \
    --enable-loadable-sqlite-extensions \
    --with-lto \
    --enable-optimizations \
    --with-valgrind
make -j

解决方案涉及这些标志之一——可能是 --with-lto--enable-optimizations