Sunday, February 18, 2018

Pyinstaller distributing opencv from Windows 10 to Windows <10, missing ucrt dlls api-ms-win-crt

Leave a Comment

I have a Python 3.5 64 bit program (required by tensorflow for Windows) that uses OpenCV. I am distributing it with pyinstaller.

I built my program with Windows 10

/c/Python35/Scripts/pyinstaller -c DeepMeerkat.spec 

On my computer, the .exe builds and runs perfectly. On any other non-Windows 10 machine

On

import cv2 

Returns

ImportError: DLL load failed: The specified module could not be found.

I can see a huge amount of discussion on this on pyInstaller thread, but I can't quite tell how to put it into practice. Dependency walker says I'm missing a number of DLLs

api-ms-win-crt-**.dll 

Okay, from the pyInstaller threads, I know that these DLLs exist

C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs 

Under multiple subfolders base on architecture.

I tried adding to my .spec file

pathex=["C:/Program Files (x86)/Windows Kits/10/Redist/ucrt/DLLs/"], 

Or for my particular architecture

pathex=["C:/Program Files (x86)/Windows Kits/10/Redist/ucrt/DLLs/arm"], 

Which is what I thought was being suggested here

"Install the Windows Software Development Kit (SDK) for Windows 10 and expand the .spec-file to include the required DLLs, see “Distributing Software that uses the Universal CRT“ in the above-mentioned link, number 6."

That did not have any effect. I am getting hundreds of errors like

121472 WARNING: lib not found: api-ms-win-crt-runtime-l1-1-0.dll dependency of c:\python35\DLLs\_ssl.pyd 

But I can see that DLL here

C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\arm 

enter image description here

So then I literally copied posthoc the entire folder

cp -r "C:/Program Files (x86)/Windows Kits/10/Redist/ucrt/DLLs/" dist/Lib/ 

But it's not clear how to connect these to the .exe. Clearly, letting pyInstaller know beforehand is preferable.

I also tried

/c/Python35/Scripts/pyinstaller --path "C:/Program Files (x86)/Windows Kits/10/Redist/ucrt/DLLs/arm" -c DeepMeerkat.spec 

And it still did not find them

I've also tried adding that folder to PATH. Any ideas?

3 Answers

Answers 1

I need to do this myself but haven't yet. I'll try to post my full solution when I do. In the mean time...

I think you may have to explicitly request they be included instead of just expanding the search path.

https://pythonhosted.org/PyInstaller/spec-files.html#adding-binary-files

Probably using the Tree class they mention to collect all the files for you.

https://pythonhosted.org/PyInstaller/advanced-topics.html#the-tree-class

Answers 2

If you would have provided your spec file I'd could see what's going on. From here its likely your not including files.

There is two methods to go from here:

  1. Create "one" single file that includes all dll's, pyd files and more... a large exe-file as result.
  2. The other way is to have it as file + folder filled with dll files, etc... you get a small exe-file.

Check add binary (incl. dll) files here the pyinstaller documentation about including files manually.

Check add data files here the pyinstaller documentation about including files manually.

An example spec-file that includes dll files from your dll folder.

block_cipher = None a = Analysis(['minimal.py'], pathex = ['/Developer/PItests/minimal'], binaries = [ ( 'C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs', '.' ) ], datas = [ ('helpmod/help_data.txt', 'helpmod' ) ], hiddenimports = [], hookspath = None, runtime_hooks = None, excludes = None, cipher = block_cipher) pyz = PYZ(a.pure, a.zipped_data, cipher = block_cipher) exe = EXE(pyz,... ) coll = COLLECT(...)

Answers 3

I've seen PyInstaller and Py2exe fail to pickup dlls countless times. Personally, I wrap my uses of them in batch or bash for a number of reasons to extend what they do. Logically, I see an argument for wrapping them in py scripts themselves...

Anyway, it may be easier to just copy the dependencies into your installation package through a wrapper script rather then fight with this.

Typically, you'll get a dll missing error thrown at you when try to run something it's missing. Add each one manually to the directory, noting what you needed to include yourself. Then script that.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment