更改导入顺序会导致Python错误

时间:2019-12-17 02:16:51

标签: python python-3.x scipy cython

我正在尝试了解以下错误的原因。首先,如果我在python中输入以下内容

>>> import scipy.sparse
>>> import torch

它运行没有错误。但是,当我输入

>>> import torch
>>> import scipy.sparse
I get the following error:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/global/software/sl-7.x86_64/modules/langs/python/3.6/lib/python3.6/site-packages/scipy/sparse/__init__.py", line 229, in <module>
    from .csr import *
  File "/global/software/sl-7.x86_64/modules/langs/python/3.6/lib/python3.6/site-packages/scipy/sparse/csr.py", line 15, in <module>
    from ._sparsetools import csr_tocsc, csr_tobsr, csr_count_blocks, \
ImportError: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by /global/software/sl-7.x86_64/modules/langs/python/3.6/lib/python3.6/site-packages/scipy/sparse/_sparsetools.cpython-36m-x86_64-linux-gnu.so)

我什至可以进入目录“ /global/software/sl-7.x86_64/modules/langs/python/3.6/lib/python3.6/site-packages/scipy/sparse/”并导入二进制文件“ _sparsetools” “ .cpython-36m-x86_64-linux-gnu.so”,然后进行无问题的割炬。但是,如果我尝试另一种方法,我会再次遇到上述错误。

有人知道为什么更改这些导入的顺序会产生不同的效果吗?

2 个答案:

答案 0 :(得分:2)

共享对象的简单搜索策略假定每个对象都有一个版本,或者至少将包含较新版本的目录放在搜索路径上。路径包括$LD_LIBRARY_PATH(应避免使用),DT_RPATH及其更新的变体DT_RUNPATH(关键取决于要加载的 client )和系统目录像/lib。对于遵循FHS且具有 global 软件包管理的系统,该方法非常有效,但已安装软件包且具有副本依赖关系的软件包在单个软件包目录中(在Windows上和某些“普通用户”程序包管理器中很常见)可以轻松地产生具有相同soname的共享对象的多个版本。

期望共享该名称是无害,因为一个名称可以代替另一个使用(因此放在路径上放在首位)。现实情况是,对于所有库来说,都没有最新的目录,并且在给定DT_标签的情况下,甚至没有一个配置的路径。

结果是,任何一个被加载的先被获胜:动态加载程序无法同时加载它们(因为它们提供了许多相同的符号),因此第二个请求仅具有效果库版本标签的检查,这在这里是不充分的。在这种情况下,一个客户端(torch)依赖于系统的C ++标准库,而另一个(_sparsetools)则拥有自己的较新版本。它可能甚至可能不需要其较新版本:由于它是针对它构建的,因此默认情况下保守地将其标记为需要它。

这是hard problem:虚拟环境或environment modules之类的工具也无法处理它,因为问题出在现成软件包的 compilation 不兼容。从重建所有内容的系统(例如NixSpack)可以,但仅以通常控制所有相关构建的成本为代价。不幸的是,很可能控制是导入顺序的最佳选择。

答案 1 :(得分:0)

@DavisHerring的答案为您提供了解释,这是一种可能的解决方法,可确保加载正确的版本-LD_PRELOAD-trick

1。步骤:

通过控制台找到正确的libc ++。so-version:

$ ldd _sparsetools.cpython-36m-x86_64-linux-gnu.so
libstdc++.so.6 => <path to right version>/libstdc++.so.6(...)

2。步骤:

启动python时,请预先加载正确的版本,以便加载程序选择正确的版本:

$ LD_PRELOAD=<path to right version>/libstdc++.so python

但是,最好的解决方案是使用正确的libc ++依赖关系重建pytorch