'OSError: cannot open shared object file: No such file or directory even though file is in the folder
I've been fighting with this for quite some time now. I'm trying to install Yaafe for audio feature extraction. I follow instructions here: https://github.com/Yaafe/Yaafe
Everything installs up nicely, but when I try to run the test file "frames.py" I get following error:
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
I have included the lib directory to LD_LIBRARY_PATH with following command:
export LD_LIBRARY_PATH=/usr/local/lib
And indeed when I echo the LIBRARY_PATH it is there. Also when I check the /usr/local/lib it has following contents:
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
So shouldn't everything be okay? I don't understand what is the problem. I've followed instructions to the point.
Solution 1:[1]
I know this post is old, but if you cannot modify (or do not want to modify) LD_LIBRARY_PATH and you still need a way to load the shared object into memory in Python, then you can use this general approach.
import ctypes
ctypes.CDLL('/usr/local/lib/library.version.so', mode=ctypes.RTLD_GLOBAL)
For you, the call might look like:
import ctypes
ctypes.CDLL('/usr/local/lib/libyaafe-python.so', mode=ctypes.RTLD_GLOBAL)
And if you don't know the path beforehand, I've put together the following function that can recursively search a set of library paths for a specified library name (and version). Hope this helps!
# 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
And for your specific example the call to the function would look like:
load_library("yaafe-python")
As long as you called this before importing whatever module was failing to load, everything should work.
WARNINGS
- This is written for POSIX systems (Ubuntu, macOS, ...)
- This loads the library into the global C namespace, so I am not sure how it will handle duplicate declarations if something already exists and it might cause unexpected downstream consequences if a loaded library is overwritten.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Thomas Lux |
