【问题标题】:Changing order of imports results in error in Python更改导入顺序会导致 Python 出错
【发布时间】:2020-04-09 12:18:51
【问题描述】:

我正在尝试了解以下错误的原因。首先,如果我在 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" 然后是火炬没有问题。但是如果我反过来尝试,我会再次遇到上述错误。

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

【问题讨论】:

  • 也许这与 torch 捆绑其依赖项的事实有关?我知道您可以(可以吗?)例如在不实际安装 CUDA 的情况下将 CUDA 与 Torch 一起使用。虽然不知道
  • 对我来说很好用(Ubuntu 18、python-3.6.9、pytorch-0.4.1、scipy-1.1.0、cudnn-7.6.4)。

标签: python python-3.x scipy cython


【解决方案1】:

共享对象的简单搜索策略假定每个共享对象都存在一个版本,或者至少将包含较新版本的目录放在搜索路径的首位。该路径包括$LD_LIBRARY_PATH(应避免使用)、DT_RPATH 及其较新的变体DT_RUNPATH(主要取决于正在加载的客户端)和系统目录,如/lib。这适用于遵循FHS 并具有global 包管理的系统,但安装的包及其依赖项的副本 在单个每个包目录中(如在 Windows 上很常见,并且对于一些“普通用户”包管理器)可以轻松生成具有相同 soname 的共享对象的多个版本。

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

结果是无论第一个加载哪个获胜:动态加载器不能同时加载它们(因为它们提供了许多相同的符号),所以第二个请求只有效果检查库版本标签,这里发现这是不够的。在这种情况下,一个客户端 (torch) 依赖于系统的 C++ 标准库,而另一个 (_sparsetools) 有自己的更新版本。它可能需要它的更新版本,也可能不需要:因为它是针对它构建的,所以默认情况下它被保守地标记为需要它。

这是一个hard problem:甚至像虚拟环境或environment modules 这样的工具都无法处理它,因为问题在于现有软件包的编译不兼容。从源代码(如NixSpack)重建所有内容的系统可以,但只能以控制所有相关构建的通常成本为代价。不幸的是,简单地控制导入顺序可能是最好的选择。

【讨论】:

    【解决方案2】:

    @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

    【讨论】:

      猜你喜欢
      • 2017-08-09
      • 2021-12-23
      • 2019-04-11
      • 1970-01-01
      • 2016-11-05
      • 2020-09-29
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      相关资源
      最近更新 更多