Search code examples
pythonpyinstaller

Add configuration file outside PyInstaller --onefile EXE file into dist directory


Situation

I'm using PyInstaller on Windows to make an EXE file of my project.

I would like to use the --onefile option to have a clean result and an easy-to-distribute file/program.

My program uses a config.ini file for storing configuration options. This file could be customized by users.

Problem

Using --onefile option, PyInstaller puts all declared "data-file"s inside the single .exe file.

I've seen this request, but it gives istructions to add a bundle file inside the onefile and not outside, at the same level of the .exe and in the same dist directory.

At some point I've thought to use a shutil.copy command inside .spec file to copy this file... but I think to be in the wrong way.

How can I fix this?


Solution

  • A repository on GitHub helped me to find a solution to my question.

    I've used the shutil module and .spec file to add extra data files (in my case, a config-sample.ini file) to dist folder using the PyInstaller --onefile option.

    Make a .spec file for PyInstaller

    First of all, I've created a makespec file with the options I needed:

    pyi-makespec --onefile --windowed --name exefilename scriptname.py
    

    This command creates an exefilename.spec file to use with PyInstaller.

    Modify exefilename.spec, adding shutil.copyfile

    Now I've edited the exefilename.spec, adding the following code at the end of the file.

    import shutil
    
    shutil.copyfile('config-sample.ini', '{0}/config-sample.ini'.format(DISTPATH))
    shutil.copyfile('whateveryouwant.ext', '{0}/whateveryouwant.ext'.format(DISTPATH))
    

    This code copies the data files needed at the end of the compile process. You could use all the methods available in the shutil package.

    Run PyInstaller

    The final step is to run the compile process

    pyinstaller --clean exefilename.spec
    

    The result is that in the dist folder you should have the compiled .exe file together with the data files copied.

    Consideration

    In the official documentation of PyInstaller I didn't find an option to get this result. I think it could be considered as a workaround... that works.