2

I've written a few Python scripts to create a tkinter GUI for a machine learning algorithm process. I originally coded everything in PyCharm, but I'd really like to put everything together into a stand-alone executable. I've moved my main script and its .py dependencies into their own directory and tested it out using the Command Prompt, and it works great. However, when I run pyinstaller, the executable is created but fails on startup.

The program is made up of three files, with GUI.py being the main script. As mentioned above, I moved the dependent files into a new directory and tested GUI.py in the Command Prompt, and it worked great. Executable is created (albeit with a lot of warnings about missing 'api-ms-win-crt' files) but can't be run.

I created the executable using the command:

pyinstaller --onefile GUI.py

When the executable is run from the command line after creation, I get a big long traceback ending in the following:

File "site-packages\sklearn\metrics\pairwise.py", line 32, in <module>
File "sklearn\metrics\pairwise_fast.pyx", line 1, in init 
    sklearn.metrics.pairwise_fast
ModuleNotFoundError: No module named 'sklearn.utils._cython_blas'
[3372] Failed to execute script GUI

I know I've already explicitly imported sklearn through the command prompt, but from the traceback, it seems I'm missing a utility module somewhere. I tried to import the missing module specifically, but I got an error that no distributed module was available. I don't have much experience with pyinstaller, and I have no idea where to go from here. I'm using Windows 10 and Python 3.7.3.

dalinar
  • 57
  • 4
  • Have you tried using `--hidden-import "sklearn.utils._cython_blas"` with your build command? – Masoud Rahimi Jul 03 '19 at 02:59
  • That did solve the error above, but it was replaced by yet another 'sklearn.' module missing. I added a few more hidden import arguments, but the ModuleNotFoundError just kept bringing up additional sklearn modules. Do you know of any way to import a module and all of its internal modules? @M.R. – dalinar Jul 03 '19 at 13:30

2 Answers2

2

It seems that Pyinstaller can't resolve sklearn import. So one easy way is to just bring the whole module directory which located in <path_to_python>/Lib/site-packages/sklearn/ with executable output. So use below spec file to generate your executable:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['test.py'],
             pathex=['<path to root of your project>'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
a.datas += Tree('<path_to_sklearn_in_python_dir>', prefix='sklearn')
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='test',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=False,
          runtime_tmpdir=None,
          console=True )

Finally generate your executable with

pyinstaller test.spec

This should resolve import errors for sklearn but if you face other NotFound imports add them like above to spec file.

Masoud Rahimi
  • 5,785
  • 15
  • 39
  • 67
  • Another [solution](https://stackoverflow.com/questions/57108026/pyinstaller-modulenotfounderror-no-module-named-sklearn-utils-cython-blas/57108887#57108887). – Masoud Rahimi Apr 11 '20 at 06:41
0

Building up on M.R.'s answer, you can directly include the path to sklearn in your original pyinstaller command:

pyinstaller --onefile GUI.py --add-data "<path-to-python>\Lib\site-packages\sklearn;sklearn"

which results in the following line of code being added inside a = Analysis() in the automatically-generated GUI.spec file:

datas=[('<path-to-python>\\Lib\\site-packages\\sklearn', 'sklearn')]

Note that the --onefile option will result in an executable that is slower to start up than the default one-folder bundle (based on both the pyinstaller documentation and my own experience bundling up sklearn):

pyinstaller GUI.py --add-data "<path-to-python>\Lib\site-packages\sklearn;sklearn"
Aciel
  • 95
  • 11