Repository: pyinstaller/pyinstaller

Issue:
matplotlib import issue: ImportError DLL load failed while importing _path...
Hey,
From searching around, matplotlib import errors occur here and there, usually the fix is to downgrade the matplotlib version, or to change the hook-matplotlib.py file. This did not resolve the issue.

matplotlib import is to blame because running the same `pyinstaller --onefile Script.py` command where matplotlib import is commented out works as expected.
Otherwise opening the newly created exe file writes these few lines before exiting (excuse me for not copying everything from the screenshot I took moments before it closed):
![Capture](https://user-images.githubusercontent.com/39532052/226161526-e02b1d64-060f-462e-9a99-6e4ae0977684.JPG)
The error:
```
ImportError: DLL load failed while importing _path: The specific module could not be found.
[5780] Failed to execute script 'Script' due to unhandled exeption!

```

During the pyinstaller run, the WARNINGS regarding matplotlib packages:
```
2149 WARNING: lib not found: msvcp140-e78ebc24b6ffa690be9375aacad743a7.dll dependency of C:\Users\...\venv\lib\site-packages\matplotlib\backends\_backend_agg.cp39-win_amd64.pyd
2189 WARNING: lib not found: msvcp140-e78ebc24b6ffa690be9375aacad743a7.dll dependency of C:\Users\...\venv\lib\site-packages\matplotlib\_path.cp39-win_amd64.pyd
2209 WARNING: lib not found: msvcp140-e78ebc24b6ffa690be9375aacad743a7.dll dependency of C:\Users\...\venv\lib\site-packages\matplotlib\backends\_tkagg.cp39-win_amd64.pyd
2239 WARNING: lib not found: msvcp140-e78ebc24b6ffa690be9375aacad743a7.dll dependency of C:\Users\...\venv\lib\site-packages\matplotlib\_tri.cp39-win_amd64.pyd
2249 WARNING: lib not found: msvcp140-e78ebc24b6ffa690be9375aacad743a7.dll dependency of C:\Users\...\venv\lib\site-packages\matplotlib\_qhull.cp39-win_amd64.pyd
2259 WARNING: lib not found: msvcp140-e78ebc24b6ffa690be9375aacad743a7.dll dependency of C:\Users\...\venv\lib\site-packages\matplotlib\ft2font.cp39-win_amd64.pyd
```

A thing to note is that my python is Anaconda distribution, so I also get this warning:
`WARNING: Assuming this is not an Anaconda environment or an additional venv/pipenv/... environment manager is being used on top, because the conda-meta folder C:\Users\...\venv\conda-meta does not exist.`
But the warning comes up with matplotlib import commented out and everything works as expected, so I doubt this has something to do with the issue.

I tried:
- Reinstalling matplotlib and pyinstaller
- Im using the Anaconda Prompt, otherwise it doesn't even get to creating the Script.exe file.
- Installing Microsoft Visual C++ 2015-2022 Redistribution.
- Changing the hook-matplotlib.py in hooks folder (it is already set right - the suggestion is old).

Info:
- Windows 10 Enterprise 64-bit
- python --version
'Python 3.9.7'
- pyinstaller --version
'5.9.0'
- matplotlib.__version__
'3.7.1'


Discussion:
Hmm, looks like `matplotlib` 3.7 got `delvewheel`'d. This went unnoticed because under regular python, collecting the shared libs is enough. On Anaconda python 3.8 and 3.9, though, `os.add_dll_directory` is defunct, so `delvhewheel` falls back to load order file, which we do not collect. We'll need to update the hook to collect the load order file as well.

In the meantime:
- switch to python.org + venv (seems you're using venv inside anaconda env anyway...)
- switch to anaconda python >= 3.10
- downgrade matplotlib to a version < 3.7
- manually ensure that load order file `site-packages\matplotlib.libs\.load-order-matplotlib-3.7.1` is collected via `--add-data-file `C:\Users\...\venv\lib\site-packages\matplotlib.libs\.load-order-matplotlib-3.7.1;matplotlib.libs`


Resolving patch:
diff --git a/PyInstaller/hooks/hook-matplotlib.py b/PyInstaller/hooks/hook-matplotlib.py
--- a/PyInstaller/hooks/hook-matplotlib.py
+++ b/PyInstaller/hooks/hook-matplotlib.py
@@ -10,6 +10,8 @@
 #-----------------------------------------------------------------------------
 
 from PyInstaller import isolated
+from PyInstaller import compat
+from PyInstaller.utils import hooks as hookutils
 
 
 @isolated.decorate
@@ -21,3 +23,16 @@ def mpl_data_dir():
 datas = [
     (mpl_data_dir(), "matplotlib/mpl-data"),
 ]
+
+binaries = []
+
+# Windows PyPI wheels for `matplotlib` >= 3.7.0 use `delvewheel`.
+# In addition to DLLs from `matplotlib.libs` directory, which should be picked up automatically by dependency analysis
+# in contemporary PyInstaller versions, we also need to collect the load-order file. This used to be required for
+# python <= 3.7 (that lacked `os.add_dll_directory`), but is also needed for Anaconda python 3.8 and 3.9, where
+# `delvewheel` falls back to load-order file codepath due to Anaconda breaking `os.add_dll_directory` implementation.
+if compat.is_win and hookutils.is_module_satisfies('matplotlib >= 3.7.0'):
+    delvewheel_datas, delvewheel_binaries = hookutils.collect_delvewheel_libs_directory('matplotlib')
+
+    datas += delvewheel_datas
+    binaries += delvewheel_binaries


Test patch: