Closed valpogus closed 5 years ago
ctypes.util.find_library() returns None if the libary is not found. In this case, ctypes.cdll.LoadLibrary() will raise a TypeError: "LoadLibrary() argument 1 must be str, not None" exception on Windows. I catch this exception and raise as OSError instead, in order to make so few changes to the original code as possible.
I guess another solution might be:
import ctypes.util
def _load_library(name):
if sys.platform == 'win32':
return ctypes.cdll.LoadLibrary(ctypes.util.find_library(name))
else:
return ctypes.cdll.LoadLibrary(name)
for name in _guess_lib_name():
try:
_libchromaprint = _load_library(name)
break
except (OSError, TypeError):
pass
else:
raise ImportError("couldn't find libchromaprint")
I have done some testing on the systems I have access to (Cygwin, Ubuntu-on-WSL, Windows 10):
#!/usr/bin/env python3
# Win10 Python 3.7
import chromaprint # OK
import ctypes
ctypes.cdll.LoadLibrary("chromaprint.dll") # OSError
ctypes.cdll.LoadLibrary("libchromaprint.dll") # OK: 'libchromaprint.dll'
ctypes.cdll.LoadLibrary("chromaprint") # OSError
ctypes.cdll.LoadLibrary("libchromaprint") # OK: 'libchromaprint'
import ctypes
import ctypes.util
ctypes.util.find_library("chromaprint.dll") # None
ctypes.util.find_library("libchromaprint.dll") # OK: 'C:\lib\libchromaprint.dll'
ctypes.util.find_library("chromaprint") # None
ctypes.util.find_library("libchromaprint") # OK: 'C:\lib\libchromaprint.dll'
import ctypes
import ctypes.util
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint.dll")) # TypeError
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.dll")) # OK: 'C:\lib\libchromaprint.dll'
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint")) # TypeError
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint")) # OK: 'C:\lib\libchromaprint.dll'
# Win10 Python 3.8
import chromaprint # ImportError
import ctypes
ctypes.cdll.LoadLibrary("chromaprint.dll") # FileNotFoundError
ctypes.cdll.LoadLibrary("libchromaprint.dll") # FileNotFoundError
ctypes.cdll.LoadLibrary("chromaprint") # FileNotFoundError
ctypes.cdll.LoadLibrary("libchromaprint") # FileNotFoundError
import ctypes
import ctypes.util
ctypes.util.find_library("chromaprint.dll") # None
ctypes.util.find_library("libchromaprint.dll") # OK: 'C:\lib\libchromaprint.dll'
ctypes.util.find_library("chromaprint") # None
ctypes.util.find_library("libchromaprint") # OK: 'C:\lib\libchromaprint.dll'
import ctypes
import ctypes.util
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint.dll")) # TypeError
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.dll")) # OK: 'C:\lib\libchromaprint.dll'
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint")) # TypeError
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint")) # OK: 'C:\lib\libchromaprint.dll'
# Ubuntu Python 3.7
import chromaprint # OK
import ctypes
ctypes.cdll.LoadLibrary("libchromaprint.so.1") # OK
ctypes.cdll.LoadLibrary("libchromaprint.so.0") # OSError
ctypes.cdll.LoadLibrary("libchromaprint.so") # OSError
ctypes.cdll.LoadLibrary("libchromaprint") # OSError
ctypes.cdll.LoadLibrary("chromaprint.so") # OSError
ctypes.cdll.LoadLibrary("chromaprint") # OSError
import ctypes
import ctypes.util
ctypes.util.find_library("libchromaprint.so.1") # None
ctypes.util.find_library("libchromaprint.so.0") # None
ctypes.util.find_library("libchromaprint.so") # None
ctypes.util.find_library("libchromaprint") # None
ctypes.util.find_library("chromaprint.so") # OK: 'libchromaprint.so.1'
ctypes.util.find_library("chromaprint") # OK: 'libchromaprint.so.1'
import ctypes
import ctypes.util
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.so.1")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.so.0")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.so")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint.so")) # OK: 'libchromaprint.so.1'
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint")) # OK: 'libchromaprint.so.1'
# Ubuntu Python 3.8
import chromaprint # OK
import ctypes
ctypes.cdll.LoadLibrary("libchromaprint.so.1") # OK
ctypes.cdll.LoadLibrary("libchromaprint.so.0") # OSError
ctypes.cdll.LoadLibrary("libchromaprint.so") # OSError
ctypes.cdll.LoadLibrary("libchromaprint") # OSError
ctypes.cdll.LoadLibrary("chromaprint.so") # OSError
ctypes.cdll.LoadLibrary("chromaprint") # OSError
import ctypes
import ctypes.util
ctypes.util.find_library("libchromaprint.so.1") # None
ctypes.util.find_library("libchromaprint.so.0") # None
ctypes.util.find_library("libchromaprint.so") # None
ctypes.util.find_library("libchromaprint") # None
ctypes.util.find_library("chromaprint.so") # OK: 'libchromaprint.so.1'
ctypes.util.find_library("chromaprint") # OK: 'libchromaprint.so.1'
import ctypes
import ctypes.util
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.so.1")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.so.0")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.so")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint.so")) # OK: 'libchromaprint.so.1'
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint")) # OK: 'libchromaprint.so.1'
# Cygwin Python 3.7
import chromaprint # OK
import ctypes
ctypes.cdll.LoadLibrary("libchromaprint.dll.a") # OSError
ctypes.cdll.LoadLibrary("cygchromaprint-1.dll") # OK
ctypes.cdll.LoadLibrary("cygchromaprint-0.dll") # OSError
ctypes.cdll.LoadLibrary("libchromaprint") # OSError
ctypes.cdll.LoadLibrary("chromaprint") # OSError
import ctypes
import ctypes.util
ctypes.util.find_library("libchromaprint.dll.a") # None
ctypes.util.find_library("cygchromaprint-1.dll") # None
ctypes.util.find_library("cygchromaprint-0.dll") # None
ctypes.util.find_library("libchromaprint") # None
ctypes.util.find_library("chromaprint") # None
ctypes.util.find_library("chromaprint.dll.a") # None
ctypes.util.find_library("chromaprint-1.dll") # None
ctypes.util.find_library("chromaprint-0.dll") # None
import ctypes
import ctypes.util
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.dll.a")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("cygchromaprint-1.dll")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("cygchromaprint-0.dll")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint")) # ERROR: loads None!
# Cygwin Python 3.8
import chromaprint # OK
import ctypes
ctypes.cdll.LoadLibrary("libchromaprint.dll.a") # OSError
ctypes.cdll.LoadLibrary("cygchromaprint-1.dll") # OK
ctypes.cdll.LoadLibrary("cygchromaprint-0.dll") # OSError
ctypes.cdll.LoadLibrary("libchromaprint") # OSError
ctypes.cdll.LoadLibrary("chromaprint") # OSError
import ctypes
import ctypes.util
ctypes.util.find_library("libchromaprint.dll.a") # None
ctypes.util.find_library("cygchromaprint-1.dll") # None
ctypes.util.find_library("cygchromaprint-0.dll") # None
ctypes.util.find_library("libchromaprint") # None
ctypes.util.find_library("chromaprint") # None
ctypes.util.find_library("chromaprint.dll.a") # None
ctypes.util.find_library("chromaprint-1.dll") # None
ctypes.util.find_library("chromaprint-0.dll") # None
import ctypes
import ctypes.util
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint.dll.a")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("cygchromaprint-1.dll")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("cygchromaprint-0.dll")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("libchromaprint")) # ERROR: loads None!
ctypes.cdll.LoadLibrary(ctypes.util.find_library("chromaprint")) # ERROR: loads None!
Important things to note:
Therefore, I would only use ctypes.util.find_library() on Windows and leave the other OSs as they are.
Wow; thank you for the detailed investigation! That thing about handling of None is quite a mess… anyway, you're absolutely right and we should clearly only use find_library
on Windows. I'll merge this now!
Thanks again for all your help. :sparkles:
Search for the chromaprint shared library on Windows using ctypes.util.find_library() and use the full path as argument for ctypes.cdll.LoadLibrary() instead of just the library name. Solves #54: "couldn't find libchromaprint" error on Windows and Python 3.8.