Pyinstaller: generate -exe file + folder (in --onefile mode)

35,197

Solution 1

Update 12/19/2013

Finally, we got it!

0. I'm working with current version of PYInstaller + Python 2.67 with Sublime Text as Editor.

1. In case your Py script requires some files, icons, images, you must include a function which retrieves these files from the project folder (in development) or form the temporary data folder (in case of deployment). This script MUST be in your code exactly in the part which you put the relatives paths in order to get the resources. Please follow exactly this guideline: https://stackoverflow.com/a/13790741

2. After the previous code, you must execute for the first time the pyinstaller command -as I post in my question post-.

3. Now, open your .spec file generated after execution of the PYInstaller (located in PYinstaller/) command and add, after "a.binaries" line, the next line into the EXE() function:

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          Tree('..\\python\\images', prefix='images\\'),
....

Keep in mind that in Tree(...) function the first argument is the folder to put outside: which means that I want to include all the content of this folder (notice that I'm putting a relative path respect to the AppStart.py file) into the file's container of my .EXE file.

4. After that modification re-execute the pyinstaller command, but in this case pointing to my .SPEC file:

pyinstaller.py --windowed --noconsole --clean --onefile AppStart\AppStart.spec

And finally my App can be executed as executable without need to copy and paste all external folders as someone mentioned. But as always I consider the good-practical way.

Thanks for your support.

Solution 2

You can also run pyinstaller within another python script then use shutil.copytree() to move the folders over after. Or use shutil.copyfile() for individual files.

import PyInstaller.__main__
import shutil

PyInstaller.__main__.run([
    'YourProgram.py',
    '--icon=UI/Your_Icon.ico',
    '--onefile',
    '--noconsole',
], )

shutil.copytree('path/', 'dist/path')

Solution 3

You have to solve many issues to get this working. For example:

  • Getting the right resource path
  • Adding data

The first issue is (as mentionned) solved by adjusting paths depending on execution mode.

def app_path(path):
    frozen = 'not'
    if getattr(sys, 'frozen', False):
            # we are running in executable mode
            frozen = 'ever so'
            app_dir = sys._MEIPASS
    else:
            # we are running in a normal Python environment
            app_dir = os.path.dirname(os.path.abspath(__file__))
    return os.path.join(app_dir, path)

For the second issue instead of tree i use the wildcard operator (*) to add what i need.

added_files = [
         ( './pics/*', 'pics' ),
         ( './db/*', 'db' ),
         ]

then in Analysis,

datas = added_files

A thorough answer is quite long. I've written this article to show in some minute details what i went through to solve the issue.

Share:
35,197

Related videos on Youtube

MigRome
Author by

MigRome

Updated on July 09, 2022

Comments

  • MigRome
    MigRome almost 2 years

    Now i'm working with Pyinstaller. I have an script which get images from a img folder..

    /python
    |----/img
    |----|----icon1.ico
    |----|----icon2.ico
    |----maint.py
    

    My script to generate .exe is

    pyinstaller.py --windowed --noconsole --clean --onefile maint.py
    

    the problem is that only generate the .exe file but the whole folder /img is omitted.

    Question: which aditional syntax do I need to put in the previous line in order to get automatically the .exe file + /img folder?

    Update 12/18/2013

    I mean: that after execution of pyinstaller.py script, with all arguments, I must see in the /dist folder: the .exe file + the /img folder with all icons or bitmaps files I have for my application

    Thanks

    • Blender
      Blender over 10 years
      What do you mean by "to get automatically the .exe file + /img folder"?
    • poke
      poke over 10 years
      Just copy that folder to /dist once the compilation process suceeded.
    • MigRome
      MigRome over 10 years
      @Blender I mean: that after execution of pyinstaller.py script, with all arguments, I must see in the /dist folder: the .exe file + the /img folder with all icons or bitmaps files I have for my application
    • MigRome
      MigRome over 10 years
      @poke Yeah, that is one alternative, but manually. I was looking for a solution with the same command. Sometimes, I will not have privileges to copy and paste a folder into the /dist folder.
    • poke
      poke over 10 years
      If you don’t have the privileges to do so, then the pyinstaller.py which you run won’t have those privileges either. In any case, just write a deploy script that (a) calls pyinstaller and (b) copies the files.
    • MigRome
      MigRome over 10 years
      @poke Thanks for your answer. But again, I look for a solution embedded in the Pyinstaller commands if it's possible.
  • denfromufa
    denfromufa about 7 years
    This is the most reliable way I have found to include full directories! Look what people are doing without this option :) stackoverflow.com/a/12033695/2230844
  • Alex Bitek
    Alex Bitek over 6 years
    The answer doesn't answer the initial question. There is no way to tell pyinstaller to copy files or directories in the dist directory by itself, instead of adding them to the bundle?
  • Lemon Calamitous
    Lemon Calamitous over 4 years
    This answer should be honored for all PyInstaller users out there. This is the only solution that worked on my end, despite numerous workaround answers.