pythonexecutablepyinstallergksudo

Packaging multiple scripts in PyInstaller


I'm using PyInstaller to turn two scripts into one executable file, one of which calls the other. The issue I'm having is I can't figure out how to bundle the two scripts and still let them reference each other:

The code that causes the issue is that one script, script1.py contains:

subprocess.call(['gksudo','python script2.py'])

This works fine when I run the scripts normally, but once they're packaged in PyInstaller I don't know how to make the call work.


Solution

  • I'm don't think pyinstaller can handle this kind of bundling on it's own, at least I didn't manage to configure it if possible. I also have a rather large application where some calls to

    subprocess.Popen('python ' ... )

    are done. The way I finally made it work was:

    1. Modify your subprocess calls to a different python, like subprocess.call(['gksudo','./python script2.py']). Create two separate analysis, one for the entry point, and one for the rest of the scripts, in your case:

      a1 - analysis of script1.py a2 - analysis of script2.py

    2. Create the exe only from the entry point scripts:

      pyz = PYZ(a1.pure)
      exe = EXE(pyz,
        a1.scripts,
        exclude_binaries=1,
        name={name here},
        debug=False,
        strip=False,
        upx=True,
        console=1 )
      
    3. Collect from all scripts

          coll = COLLECT( exe,
             a1.binaries,
             a1.zipfiles,
             a1.datas,
             a2.binaries,
             a2.zipfiles,
             a2.datas,
         python_tree, 
             *additional_trees,
             strip=False,
             upx=True,
             name={})
      
    4. Copy python in your distribution at location that was specified in all the subprocess calls with any additional requirements that were not found by pyinstaller (i had a few like matplotlib, pylab etc)

    5. Create a start script that first changes any required enviromental variables to point to your package and then start the app. In my case what was needed was, from calling directory:

       export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
       export LD_RUN_PATH=`pwd`:$LD_RUN_PATH
      

    Now all of these was required if I wanted the application to run on machines that either had no python installed, or if they have python installed, make sure the app still uses all the libraries from the distribution package instead of any local libraries. If in your case python is already installed on target machines I don't think anything like this would be necessary and first 3 steps would suffice.