I am trying to make an executable of my Python code which uses Tensorflow
with Pyinstaller
. The executable gets generated correctly but when I try to run it, I get the following error:
Traceback (most recent call last):
File "detection_init.py", line 14, in <module>
import lib.tensorboxDetector as tensorboxDetector
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "lib/tensorboxDetector.py", line 26, in <module>
from lib.train import build_forward
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "lib/train.py", line 4, in <module>
import tensorflow.contrib.slim as slim
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "tensorflow/contrib/__init__.py", line 22, in <module>
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "tensorflow/contrib/bayesflow/__init__.py", line 24, in <module>
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "tensorflow/contrib/bayesflow/python/ops/csiszar_divergence.py", line 26, in <module>
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "tensorflow/contrib/bayesflow/python/ops/csiszar_divergence_impl.py", line 42, in <module>
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "tensorflow/contrib/framework/__init__.py", line 89, in <module>
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "tensorflow/contrib/framework/python/ops/__init__.py", line 24, in <module>
File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyimod03_importers.py", line 396, in load_module
exec(bytecode, module.__dict__)
File "tensorflow/contrib/framework/python/ops/checkpoint_ops.py", line 32, in <module>
File "tensorflow/contrib/util/loader.py", line 55, in load_op_library
File "tensorflow/python/framework/load_library.py", line 64, in load_op_library
tensorflow.python.framework.errors_impl.NotFoundError: tensorflow/contrib/util/tensorflow/contrib/framework/python/ops/_checkpoint_ops.so: cannot open shared object file: No such file or directory
[11241] Failed to execute script detection_init
If we look carefully, Pyinstaller is expecting the file _checkpoint_ops.so
in directory tensorflow/contrib/util/tensorflow/contrib/framework/python/ops/
but there's no directory like this. _checkpoint_ops.so
is located at tensorflow/contrib/framework/python/ops/
. How can this error be corrected?
The most common reason a PyInstaller package fails is that PyInstaller failed to bundle a required file. Such missing files fall into a few categories: Hidden or missing imports: Sometimes PyInstaller can't detect the import of a package or library, typically because it is imported dynamically.
To find out, PyInstaller finds all the import statements in your script. It finds the imported modules and looks in them for import statements, and so on recursively, until it has a complete list of modules your script may use.
python - PyInstaller does not include imports - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.
Add the following to your spec file (finds tensorflow binaries and adds them to your .app in the main binary/file directory):
import os
tensorflow_location = '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow'
tensorflow_binaries = []
for dir_name, sub_dir_list, fileList in os.walk(tensorflow_location):
for file in fileList:
if file.endswith(".so"):
full_file = dir_name + '/' + file
print(full_file)
tensorflow_binaries.append((full_file, '.'))
Make sure you also add the binaries to Analysis
a = Analysis(...,
binaries=tensorflow_binaries,
...)
And make sure binaries are included in the .exe/.app builds. Here's a simple example:
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='TestApp',
debug=True,
strip=None,
upx=True,
console=True, icon='Test.icns')
app = BUNDLE(exe,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='Test.app',
icon='Test.icns',
bundle_identifier='com.Test.TestApp',
info_plist={
'NSHighResolutionCapable': 'True'
},
)
The last thing you need to do is modify the tensorflow load_library.py
file to point to the relative path of the binaries during .app runtime.
The file is usually located here (relative to python install): site-packages/tensorflow/python/framework/load_library.py
You need to add the resource_path
function and modify the load_op_library
function to point the file_name to the relative path (and to ignore finding binaries by sub-folder).
def resource_path(relative_path):
"""Due to pyinstaller changing root dir of project filenames need to be processed in order to open properly
Parameters
----------
relative_path : str
String containing filename path
Returns
-------
path : str
path relative to this file on local computer
"""
import sys
import os
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
path = os.path.join(base_path, relative_path)
return path
def load_op_library(library_filename):
"""Loads a TensorFlow plugin, containing custom ops and kernels.
Pass "library_filename" to a platform-specific mechanism for dynamically
loading a library. The rules for determining the exact location of the
library are platform-specific and are not documented here. When the
library is loaded, ops and kernels registered in the library via the
`REGISTER_*` macros are made available in the TensorFlow process. Note
that ops with the same name as an existing op are rejected and not
registered with the process.
Args:
library_filename: Path to the plugin.
Relative or absolute filesystem path to a dynamic library file.
Returns:
A python module containing the Python wrappers for Ops defined in
the plugin.
Raises:
RuntimeError: when unable to load the library or get the python wrappers.
"""
# REMOVE AFTER PYINSTALLER USE
library_filename = resource_path(library_filename.split('/')[-1])
This will make tensorflow fetch the binaries by the relative path of your pyinstaller application (See: https://pythonhosted.org/PyInstaller/runtime-information.html#run-time-information).
Tensorflow will then fetch the binaries as packaged by the .spec
file.
Remember to uncomment the library_filename = resource_path(library_filename.split('/')[-1])
line in load_library.py
after Pyinstaller packaging (or else Tensorflow won't be able to find the binaries when running in your local Python env!)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With