0

Using the 3.3.1 pyinstaller in python 3.5 32bit, I converted a .py application to .exe

The application uses tensorflow and at some point throws

Traceback (most recent call last):
  File "face_classify.py", line 140, in <module>
    loaded_model = load_c3d.c3d_model_obj(user_case)
  File "load_c3d.py", line 80, in __init__
    'wc1': _variable_with_weight_decay('wc1', [3, 3, 3, 3, 64], 0.0005),
  File "load_c3d.py", line 47, in _variable_with_weight_decay
    var = _variable_on_cpu(name, shape, tf.contrib.layers.xavier_initializer())
  File "site-packages\tensorflow\__init__.py", line 35, in __getattr__
  File "importlib\__init__.py", line 126, in import_module
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 956, in _find_and_load_unlocked
ImportError: No module named 'tensorflow.contrib'

This happens when running the .exe. Looks like a file path issue. The __init__.py of tensorflow does this

# Lazily import the `tf.contrib` module. This avoids loading all of the
# dependencies of `tf.contrib` at `import tensorflow` time.
  def __getattr__(self, item):
    global contrib
    # Replace the lazy loader with the imported module itself.
    import importlib  # pylint: disable=g-import-not-at-top
    contrib = importlib.import_module('tensorflow.contrib')
    return getattr(contrib, item)

To me it looks like this lazy loading cannot be tracked by pyinstaller. However the contrib folder is correctly placed inside my python installation: C:\Python35\Lib\site-packages\tensorflow\contrib How can I solve this issue?

Tasos
  • 1,575
  • 5
  • 18
  • 44

4 Answers4

2

In my case, you can add 'tensorflow.contrib' in your hiddenimport from the .spec file. However, I met another problem after I fix the import, but you can first try this at least.

  • We ended up removing the usage of tensorflow.contrib in the code (it was used to provide a random initialization). But your comment is useful. Upgrading Tensorflow (tried up to version 1.3) did not fix the issue btw. – Tasos Jun 05 '18 at 16:57
  • 1
    I ended up manually adding all the .so file in the .spec file, and it works finally. In my case, the problem is that tensorflow contrib uses a tons of lazy loaders and relative path, so if you do not manually add all the files, pyinstaller cannot find them. – Yicheng Wang Jun 09 '18 at 06:23
2

Hope this helps anyone having

`ModuleNotFoundError: No module named 'sklearn.*'`

`ModuleNotFoundError: No module named 'h5py.*'`

During or after building pyinstaller

Example if you get an error for h5py

After running pyinstaller myscript.py a myscript.spec is generated

Go inside myscript.spec

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

a = Analysis(['myscript.py'],
         binaries=None,
         datas=[],
         hiddenimports=[],
         hookspath=[],
         runtime_hooks=[],
         excludes=[],
         win_no_prefer_redirects=False,
         win_private_assemblies=False,
         cipher=None)
# ... rest of a file untouched

Add

from PyInstaller.utils.hooks import collect_submodules

hidden_imports = collect_submodules('h5py')

and

hiddenimports=hidden_imports,

Like this

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

from PyInstaller.utils.hooks import collect_submodules

hidden_imports = collect_submodules('h5py')

a = Analysis(['myscript.py'],
         binaries=None,
         datas=[],
         hiddenimports=hidden_imports,
         hookspath=[],
         runtime_hooks=[],
         excludes=[],
         win_no_prefer_redirects=False,
         win_private_assemblies=False,
         cipher=None)
# ... rest of a file untouched

Then Save myscript.spec and run command pyinstaller myscript.spec

Credit to 9dogs Pyinstaller created exe file can not load a keras nn model

0

you can add ‘tensorflow.contrib’ to --hidden-import

pyinstaller -F face_classify.py --hidden-import tensorflow.contrib

周远远
  • 1
  • 1
0

Even pyinstaller 4.0 (latest stable version today) has this error. But there is a workaround if you don't use the --one_file. Compile your program with --hiddenimports="tensorflow.contrib" and then copy all .so from tensorflow.contrib to where your executable looks for them. So, you need to create the contrib folder inside tensorflow and then copy the libraries.

mkdir path_to_dist/app_name/tensorflow/contrib
cd /usr/local/lib/python3.6/dist-packages/tensorflow/contrib && find ./ -name *.so |xargs -i cp --parents {} path_to_dist/app_name/tensorflow/contrib/

change the python version if you are not using python 3.6.

I don't know how to make this with --one_file.

Credits for andrewjong and aodiwei from github. The solution is on this issue.

Israel P
  • 41
  • 3