Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build images and some configuration files like txt and xml files with pyinstaller

I have a trouble with pyinstaller when adding some data files like images and txts to python program. For example, I have created a toolbar with icons, and I store them in a seperate folder named images. Also I have some some txt and xml files to store some configurations. These txt ant xml files are stored in another folder named data_files. All the py files are stored in another folder named source.

When I am trying to build this python program with pyinstaller, pyinstaller can successfully build all of the source folder, but the images and data_files folders can not be built. I checked the documentation of pyinstaller but I could not find any solution. I have made a lot of google searches and found only this resourse as helpful, but this is a very inadequate resource.

My main question is: How can I build an exe file with a separately built folder such as images and confs by using pyinstaller?

Edit: I found the solution. When you create the spec file you have to a.datas parameter.

# -*- mode: python -*-
a = Analysis([os.path.join(HOMEPATH,'support/_mountzlib.py'), os.path.join(HOMEPATH,'support/useUnicode.py'), '/home/vmode/Desktop/derlem2/sources/TextSTAT.py'],
             pathex=['/home/pyinstaller'])
a.datas += [("Images/New.gif","/home/vmode/Desktop/derlem2/Images/New.gif","DATA")]
a.datas += [("Images/Open.gif","/home/vmode/Desktop/derlem2/Images/Open.gif","DATA")]
a.datas += [("Images/Column.gif","/home/vmode/Desktop/derlem2/Images/Column.gif","DATA")]
pyz = PYZ(a.pure)
exe = EXE( pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name=os.path.join('dist', 'TextSTAT'),
          debug=False,
          strip=False,
          upx=True,
          console=1 )

The above spec code is designed for my project. As seen in this spec code I have included 3 icons to build with the python program. When the programme is generated there is a standalone executable file with embedded these icons.

But what if we have so many files? Suppose that we have 1000 icons to use in our program. It is very inadequate to write down to spec file by hand. There must be a loop system to read the file directory and add these files dynamically. But I could not find how to add these files dynamically. There is no any chance to add these so many files by hand I think. If anyone knows please share.

like image 776
user1150508 Avatar asked Jan 15 '12 15:01

user1150508


People also ask

What is pyinstaller in Python?

What is pyinstaller The pyinstaller module makes you able to create a standalone exe file for pc from a python script, so that you can use it on other computers than do not have python or your python version.

How to move the picture of a pyinstaller program?

You can not move the picture, and the picture need to stay with the executable file. This is another easy way to display our picture. We use absolution path to replace the relative path, and we use PyInstaller to package this program again. This time, we have no picture under our executable file directory. But when we execute the test_GUI.exe:

Why can’t pyinstaller link pictures together?

External materials such as pictures are one of the objects that PyInstaller will not link together, so this loophole is exploited and the bytes of the picture are directly stored in the .py file. If the .py files are not successfully packaged, it means that this module really has a big loophole.

Why does pyinstaller show icons that are not in the platform format?

If an image file is entered that isn’t in the platform format (ico on Windows, icns on Mac), PyInstaller tries to use Pillow to translate the icon into the correct format (if Pillow is installed). Use “NONE” to not apply any icon, thereby making the OS show some default (default: apply PyInstaller’s icon)


2 Answers

In creating my executable, I came across this problem as well. Because the .spec file is using python, glob module was my solution.

imagesList = []
imagesList.append( ('icon.ico', '..\\pathfinder\\icon.ico',  'DATA') )
import glob
allImages = glob.glob('..\\pathfinder\\*.png')
for eachImage in allImages:
    imageParts = eachImage.split('\\')
    imagesList.append( (imageParts[-1], eachImage,  'DATA') )
print imagesList
a.datas += imagesList

Line 2 regarding icon.ico was separate because it had a different file extension, and can thus be excluded. '..\pathfinder' is the path for all of my program's files (relative from pyinstaller directory). glob searches the directory for all .png files (I have 65 and refused to write them all by hand) and returns a list of them as strings, full relative directory intact. To separate it into a list of filenames, I used string.split() on backslash. Then for each, append to a user-made list a tuple of the final part of the string split (which would end up being just the filename of the image) and the full pathname. Finally, with a list of all the files, add it to a.datas.

I've confirmed through the command line that this does indeed work correctly, and you can re-copy the loop for any additional file extensions.

Unfortunately, even though it seems to pull and attach the filenames correctly, my executable still does not seem to be created with the files (or the executable cannot find the files within its own data) and I still have to have the raw images in the same directory for it to work; perhaps I have the elements of the tuple ordered incorrectly (and thus, if so, you should adjust my code accordingly). Hopefully, this dynamic load will still work for you, though. imageParts[-1] represents each .png's filename, and eachImage represents its full path (or relative path if that's what was used in glob).

like image 89
Mark Avatar answered Oct 22 '22 04:10

Mark


If all images are listed under same directory you can use Tree

dict_tree = Tree('/home/vmode/Desktop/derlem2/Images', prefix = 'Images')
a.datas += dict_tree
like image 39
hithwen Avatar answered Oct 22 '22 04:10

hithwen