Cannot load MediaInfo.dll (windows) from Python 3.8
anjos opened this issue · 10 comments
Apparently, there is a nasty bug/miscommunication starting with Python 3.8 regarding the way to search for DLLs under Windows. As a result, conda-forge builds for this package under win-64/python3.8 are broken (log of the build: https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=410706&view=logs&jobId=5be07ae1-d8ba-5406-47b6-8e3a3a12f825&j=5be07ae1-d8ba-5406-47b6-8e3a3a12f825&t=0bf03e01-0bec-5b85-5316-b1633322e895)
The problem is rather trivial: ctypes.WinDLL
does not find MediaInfo.dll
(details and solution here: https://stackoverflow.com/questions/59330863/cant-import-dll-module-in-python).
How to fix: When the DLL is loaded, one has to set winmode=0
to recover the old DLL finding behaviour, around line 314 of pymediainfo/__init__.py
(v5.1.0).
I can add this as a patch to the build instructions, but I thought you may want to consider this to be pushed upstream, @sbraz.
As expected, things work OK with Python 3.7 and somehow with Python 3.9 as well. I could not test it yet with Python 3.10. Please let me know how you want to proceed.
Hi,
According to the documentation, winmode=0
is the default. I guess the documentation is wrong?
It's strange that the AppVeyor builds never failed. I'll look into it.
Yes, that seems to be wrong in the documentation as explained in the StackOverflow thread above (it is actually set to None
instead, and that makes a difference). I had a look at the AppVeyor builds, but in that case you copy the dll to somewhere with ps: "Copy-Item -Path MediaInfo.dll -Destination ${Env:PYTHON}"
? I wonder if that does not bypass this fault somehow?
Patch tested on conda-forge: conda-forge/pymediainfo-feedstock@96fda70
Sorry for the delay, I tried the following:
- Installed Python 3.8.10 on Windows 10
- Ran
pip.exe install pymediainfo
(pip installedpymediainfo-5.1.0-py3-none-win_amd64.whl
) - Ran
C:\Python38\python.exe -c "import pymediainfo; print(pymediainfo.MediaInfo.parse('test.png'))"
which worked as expected.
This probably works because the DLL is in the wheel. However, what failed for me was:
git clone https://github.com/sbraz/pymediainfo/
cd pymediainfo
# Downloaded MediaInfo.dll
C:\Python38\python.exe -c "import pymediainfo; print(pymediainfo.MediaInfo.parse('test.png'))"
It resulted in:
OSError: Failed to load library from MediaInfo.dll - Could not find module 'MediaInfo.dll' (or one of its dependencies). Try using the full path with constructor syntax.
I also tried with a range of Python versions: 3.6 and 3.7 work; 3.8, 3.9 and 3.10 fail.
Settingwinmode=0
fixes the problem with >= 3.8 versions but is not accepted on 3.6 and 3.7 so the patch will need to include an if sys.version < (3, 8)
.
I've found a better way: using the absolute path fixes the problem:
diff --git a/pymediainfo/__init__.py b/pymediainfo/__init__.py
index 9c18679..a2458c0 100644
--- a/pymediainfo/__init__.py
+++ b/pymediainfo/__init__.py
@@ -310,6 +310,7 @@ class MediaInfo:
library_paths = (library_file,)
exceptions = []
for library_path in library_paths:
+ library_path = os.path.abspath(library_path)
try:
lib = lib_type(library_path)
cls._define_library_prototypes(lib)
Can you please try that?
I've filed a PR for the doc problem: python/cpython#29976
Thanks for the doc patch - it will help. For the actual patch you propose, it seems that it works well under OSX (arm, M1), but not for Windows, Linux or OSX (intel): https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=424833&view=logs&jobId=4f922444-fdfe-5dcf-b824-02f86439ef14&j=4f922444-fdfe-5dcf-b824-02f86439ef14&t=b2a8456a-fb11-5506-ca32-5ccd32538dc0
Note: In the case of conda-forge, the library is installed together with other DLLs, in an environment-wide installation. To create a setup to work with, you can do the following:
- Install miniforge or, better, mambaforge from https://github.com/conda-forge/miniforge
- Create an environment to work with:
conda create -n test python=3.8 mediainfo
- Clone your package in a work directory, then pip install it in editable mode:
pip install -e .
- Run the tests
I hope it helps.
You're right, my patch is not ideal because on Linux we don't always provide a full path.
I'm really not keen on setting winmode=0
as it might have security implications. Have you considered using os.add_dll_directory()
so that your system-wide DLL location is properly recognised? Surely this would benefit other packages besides pymediainfo.
There is one curious thing: the patch at conda-forge is only applied if sys.version = (3, 8)
. We can then speculate that this problem is actually temporary and will be auto-fixed when python 3.8 is deprecated. I propose we leave it as is in this case.