1

I have been trying to bundle a project into one single file using PyInstaller. I have successfully added all the required binaries and additional files, except for files in one single folder for which I have tried the solutions to other similar questions like this and this to no avail. I also went through the documentation but I think I am still missing something. I have tried adding using both relative path and absolute path. My Project structure is as follows,

Project_Root_Folder
    model(folder)
        model.json file
        .h5 file
    other_data_folders
    other.py files
    other_binaries

My spec file,

import PyInstaller.utils.hooks as hooks
from glob import glob
import os
from PyInstaller.utils.hooks import collect_submodules, collect_data_files
tensorflow_location = '/home/user/miniconda3/envs/project/lib/python3.7/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, '.'))

def resource_path(relative):
    return os.path.join(os.environ.get("_MEIPASS2", os.path.abspath(".")), relative)

block_cipher = None
added_binaries = [('_pytransform.so','.'),('lanms/adaptor.so','.')]
#added_files = collect_data_files('nltk',False)
added_files = [
        ('pytransform.*','.'),
        #('/home/user/nltk_data',"nltk_data"),
        ('lanms/*','lanms'),
        (resource_path('model/*'),'model'),
        (resource_path('model/model.json'),'model') 

hidden_imports = []+collect_submodules('scipy.ndimage')+collect_submodules('shapely.geometry')
added_binaries = added_binaries + tensorflow_binaries
__file__ = 'run.spec'

cur_dir = os.path.dirname(os.path.abspath(__file__))
a = Analysis(['run.py'],
             pathex=[cur_dir,
              ],
             binaries=[('./_pytransform.so','.')]+tensorflow_binaries,
             datas=added_files,
             hiddenimports=hidden_imports,
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='project',
          debug=False,
          strip=False,
          upx=True,
          console=True )

After the bundling process is complete and I run the binary, it says it is unable to locate 'model/model.json'. When I place the model folder in the same folder as the binary the project works as intended but I am unable to bundle it along with the other files,folders and binaries into the same 'onefile'. What am I missing.

Guimoute
  • 4,407
  • 3
  • 12
  • 28
REVOLUTION
  • 130
  • 2
  • 12

1 Answers1

0

I figured out what I was doing wrong. I will share it here in case someone else gets stuck in the same silly way I did. In the program when I load the json file, I was supposed to load it using the resource_path function.I was using the resource_path function in the spec file previously.

def resource_path(relative):
    return os.path.join(
        os.environ.get(
            "_MEIPASS2",
            os.path.abspath(".")
        ),
        relative
    )
json_file = open(resource_path(previously_used_path),'r')
REVOLUTION
  • 130
  • 2
  • 12
  • That ensures the path changes dynamically depending on whether the app is in its development environment or deployment environment. – Guimoute Nov 26 '19 at 15:13