Search code examples
pythonpyinstallerexecutable

How to pack a python to exe while keeping .py source code editable?


I am creating a python script that should modify itself and be portable.

I can achieve each one of those goals separately, but not together.

I use cx_freeze or pyinstaller to pack my .py to exe, so it's portable; but then I have a lot of .pyc compiled files and I can't edit my .py file from the software itself.

Is there a way to keep a script portable and lightweight (so a 70mb portable python environment is not an option) but still editable?

The idea is to have a sort of exe "interpreter" like python.exe but with all the libraries linked, as pyinstaller allows, that runs the .py file, so the .py script can edit itself or be edited by other scripts and still be executed with the interpreter.


Solution

  • First define your main script (cannot be changed) main_script.py. In a subfolder (e.g. named data) create patch_script.py

    main_script.py:

    import sys
    sys.path.append('./data')
    import patch_script
    

    inside the subfolder:

    data\patch_script.py:

    print('This is the original file')

    In the root folder create a spec file e.g. by running pyinstaller main_script.py. Inside the spec file, add the patch script as a data resource:

         ...
         datas=[('./data/patch_script.py', 'data' ) ],
         ...
    

    Run pyinstaller main_sript.spec. Execute the exe file, it should print

    This is the original file

    Edit the patch script to e.g. say:

    print('This is the patched file')

    Rerun the exe file, it should print

    This is the patched file

    Note: As this is a PoC, this works but is prone to security issues, as the python file inside the data directory can be used for injection of arbitrary code (which you don't have any control of). You might want to consider using proper packages and update scripts as used by PIP etc.