OSError: cannot open shared object file: No such file or directory even though file is in the folder

OSError: cannot open shared object file: No such file or directory even though file is in the folder

我已经和这个问题斗争了很长一段时间了。我正在尝试安装 Yaafe 以提取音频特征。我按照此处的说明进行操作:https://github.com/Yaafe/Yaafe

一切都安装得很好,但是当我尝试 运行 测试文件 "frames.py" 时,出现以下错误:

  File "frames.py", line 6, in <module>
    from yaafelib import FeaturePlan, Engine, AudioFileProcessor 
  File "/usr/local/lib/python2.7/dist-packages/yaafelib/__init__.py", line 36, in <module>
    from yaafelib.core import (loadComponentLibrary,
  File "/usr/local/lib/python2.7/dist-packages/yaafelib/core.py", line 35, in <module>
    yaafecore = cdll.LoadLibrary('libyaafe-python.so')
  File "/usr/lib/python2.7/ctypes/__init__.py", line 443, in LoadLibrary
    return self._dlltype(name)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: libyaafe-python.so: cannot open shared object file: No such file or directory

我已使用以下命令将 lib 目录包含到 LD_LIBRARY_PATH:

export LD_LIBRARY_PATH=/usr/local/lib

确实,当我回显 LIBRARY_PATH 时,它就在那里。此外,当我检查 /usr/local/lib 时,它包含以下内容:

libyaafe-components.so         libyaafe-io.so             python2.7
libyaafe-components.so.0       libyaafe-io.so.0           python3.4
libyaafe-components.so.0.70.0  libyaafe-io.so.0.70.0      site_ruby
libyaafe-core.so               libyaafe-python.so         yaafe
libyaafe-core.so.0             libyaafe-python.so.0
libyaafe-core.so.0.70.0        libyaafe-python.so.0.70.0

所以不应该一切都好吗?我不明白这是什么问题。我已按照说明进行操作。

更改您的代码,以便在异常发生之前打印 os.environ。这样你就会看到 Python 进程是否设置了正确的环境。另一个明显要检查的事情是您的 Python 进程是否有足够的权限打开和读取 libyaafe-python.so。请注意,出于安全原因,sudo 默认情况下会限制调用命令的环境(例如,请参阅 here)。

我知道这个post是旧的,但是如果你不能修改(或不想修改)LD_LIBRARY_PATH并且你仍然需要一种方法来将共享对象加载到[=中的内存中36=],那么就可以用这个通用的方法了。

import ctypes
ctypes.CDLL('/usr/local/lib/library.version.so', mode=ctypes.RTLD_GLOBAL)

对你来说,电话可能是这样的:

import ctypes
ctypes.CDLL('/usr/local/lib/libyaafe-python.so', mode=ctypes.RTLD_GLOBAL)

如果您事先不知道路径,我已经整理了以下函数,可以递归搜索一组库路径以查找指定的库名称(和版本)。希望这对您有所帮助!


# Given a library name, try to locate the library and load it in
#  global mode as a CDLL so that it is accessible to all code.
def load_library(libname, version=None, paths=("/usr/lib","/usr/local/lib",),
                 extensions=(".so",), prefixes=("","lib",),
                 recursive=True):
    import os, ctypes
    # This code will find all possible matches for the library, 
    #  and pick the first lexicographically.
    versions = set()
    for directory in paths:
        # Enumerate all files at that path (depending on "resursive" option).
        if recursive:
            file_paths = sum((
                [os.path.join(dirpath, f) for f in filenames]
                for (dirpath, dirnames, filenames) in os.walk(directory)
            ), [])
        else:
            file_paths = [
                os.path.join(directory,f) for f in os.listdir(directory)
                if not os.path.isdir(f)
            ]
        # Iterate over the files looking for the specified library.
        for path in file_paths:
            filename = os.path.basename(path)
            # Verify the file extension is allowed.
            ext = filename[len(filename)-filename[::-1].find('.')-1:] 
            # Examples of the value for 'ext' given a 'filename':
            #   "foo.bar" -> ".bar", "foobar" -> ""
            if (ext not in extensions): continue
            # Check that the library name is in file name.
            if (libname not in filename): continue
            # Check that the version is in the name (if it is specified).
            file_version = ".".join(filename.split('.')[1:-1])
            if ((version is not None) and (version != file_version)): continue
            # Extract the file name and check for matches against prefixes.
            name = filename[:(filename+'.').find('.')]
            for p in prefixes:
                if (p+libname == name): break
            else: continue
            # Now this filename matches the required:
            #   name preceding the first ".",
            #   file extension including last ".",
            #   version between first and last "." if that was specified,
            #   and it exists in one of the provided paths.
            versions.add(path)
            # Uncomment the following line to see the considered libraries.
            # print([path, filename, name, file_version, ext, os.path.islink(path)])
    # Raise an error if no versions could be found.
    if (len(versions) == 0):
        raise(FileNotFoundError(f"No library file found for '{libname}'{'' if version is None else ' version '+version}."))
    # Get the library path as the first element of the set of discovered versions.
    library_path = sorted(versions)[0]
    # Load the library globally (so it is accessible to later codes) and return its path.
    ctypes.CDLL(library_path, mode=ctypes.RTLD_GLOBAL)
    return library_path

对于您的特定示例,对该函数的调用如下所示:

load_library("yaafe-python")

只要您在 之前调用这个 导入任何无法加载的模块,一切都应该有效。

WARNINGS

  • 这是为 POSIX 系统(Ubuntu、macOS、...)编写的
  • 这会将库加载到全局 C 命名空间中,因此我不确定如果某些内容已经存在,它将如何处理重复声明,并且如果加载的库被覆盖,它可能会导致意外的下游后果。