How to compile all resources into one executable file?
Asked Answered
G

3

7

I've wrote GTK application with python.

All graphical user interface is in glade file, and there are some images used. I wish to compile my application into EXEcutable file. For that I'm using PyInstaller compiler and UPX packer.

I've done as manual says:

python Configure.py
python Makespec.py --onefile --windowed --upx /path/to/yourscript.py
python Build.py /path/to/yourscript.spec

PyInstaller works perfectly and create one exe file. But to make my application work correctly i have to copy my glade and image files into exe's folder.

Is there any way to compile those files into executable?

I've edited my spec file in various ways but i can not achieve what i want. Spec file below only copies file to directory, but does not compile into executable file

# -*- mode: python -*-
a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), 'r:\\connection\\main.py'],
             pathex=['C:\\Documents and Settings\\Lixas\\Desktop\\pyinstaller-1.5-rc1'])

pyz = PYZ(a.pure)

exe = EXE( pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name=os.path.join('dist', 'NetworkChecker.exe'),
          debug=False,
          strip=False,
          upx=True,
          console=False,
          icon='r:\\connection\\ikona.ico'        )

coll = COLLECT(
    exe,
    [('gui.glade', 'r:\\connection\\gui.glade', 'DATA')],
    [('question16.png', 'r:\\connection\\question16.png', 'DATA')],
#   a.binaries,
#   strip=False,
    upx=True,
    name='distFinal')

I wish to have only one executable file with everything included into

Gelding answered 14/7, 2011 at 6:43 Comment(0)
L
6

PyInstaller does allow you to bundle all your resources into the exe, without the trickyness of turning your data files into .py files -- your COLLECT object seems to be correct, the tricky step is accessing these files at runtime. PyInstaller will unpack them into a temporary directory and tell you where they are with the _MEIPASS2 variable. To get the file paths in both development and packed mode, I use this:

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


# in development
>>> resource_path("gui.glade")
"/home/shish/src/my_app/gui.glade"

# in deployment
>>> resource_path("gui.glade")
"/tmp/_MEI34121/gui.glade"
Least answered 6/10, 2011 at 13:52 Comment(3)
This is no longer an environment variable, this is now stored in sys._MEIPASSMarji
@favilo: Can you tell us how that will change this code to make it work?Homerhomere
You may be able to help solve my problem.Morass
F
6

With a few changes, you can incorporate everything into your source code and thus into your executable file.

If you run gdk-pixbuf-csource on your image files, you can convert them into strings, which you can then load using gtk.gdk.pixbuf_new_from_inline().

You can also include your Glade file as a string in the program and then load it using gtk.Builder.add_from_string().

Ferrite answered 14/7, 2011 at 11:31 Comment(3)
That was idea that i thought of earlier- incorporate resources in script. Thank you for pointing me the way how to incorporate resources into app exe file.Gelding
+1 because in light of the comments of the OP this makes possible to obtain what he wanted to. I still miss to understand what the advantages of having everything in a single runtime file are, though... but this is not a problem of your answer, of course! :)Twotone
You may be able to help solve my problem.Morass
L
6

PyInstaller does allow you to bundle all your resources into the exe, without the trickyness of turning your data files into .py files -- your COLLECT object seems to be correct, the tricky step is accessing these files at runtime. PyInstaller will unpack them into a temporary directory and tell you where they are with the _MEIPASS2 variable. To get the file paths in both development and packed mode, I use this:

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


# in development
>>> resource_path("gui.glade")
"/home/shish/src/my_app/gui.glade"

# in deployment
>>> resource_path("gui.glade")
"/tmp/_MEI34121/gui.glade"
Least answered 6/10, 2011 at 13:52 Comment(3)
This is no longer an environment variable, this is now stored in sys._MEIPASSMarji
@favilo: Can you tell us how that will change this code to make it work?Homerhomere
You may be able to help solve my problem.Morass
T
1

Is there any way to compile those files into executable?

Strictly speaking: no, because you compile source code, while the glade file is XML and the images are binary data. What you would normally do is to create an installer (i.e. a self-unpacking archive that will place different files in the correct directories when the installer is ran).

EDIT: If your concern is simply to have a one-file executable (so it's not about "compiling" but really about the number of files that are permanently written on the filesystem) you could try to use this script based on py2exe. What it does, is to create temporary files each time the program is ran, removing them when execution is completed.

EDIT2: Apparently what you are asking for is also possible under PyInstaller. From the documentation:

By default, pyinstaller.py creates a distribution directory containing the main executable and the dynamic libraries. The option --onefile specifies that you want PyInstaller to build a single file with everything inside.

Twotone answered 14/7, 2011 at 7:46 Comment(3)
I wish to make ultra-portable application, where you need to worry just about one file. But if it is not possible this way- i will try to implement image and glade files into python script code. Thank you very much Maybe someone else has any other opinions about my problemGelding
@Gelding - I don't really understand why you want to pursue this road (I'm not criticising: I'm asking for clarification, as I can't see its benefits to the user, while I can see its drawbacks). However if what you care is the number of files and not the fact that they are executable, see my edit, where I linked a script that does pretty much what you asked for, if I got the documentation right.Twotone
You may be able to help solve my problem.Morass

© 2022 - 2024 — McMap. All rights reserved.