squirrelgod17
squirrelgod17

Reputation: 73

Pyinstaller: Images fail to extract

I run the build command and everything appears to build correctly until I try to launch the exe and this message pops up:

Image

Here is my spec file, I am not sure why it appears to be combing the file path with both images.

block_cipher = None

a = Analysis(['TripCalc.py'],
         pathex=['C:\\Users\\test\\Downloads\\TripApp'],
         binaries=[],
         datas=[('C:\\Users\\test\\Downloads\\TripApp\\BennySM.ico', 'C:\\Users\\test\\Downloads\\TripApp\\BgSM.gif')],
         hiddenimports=[],
         hookspath=[],
         runtime_hooks=[],
         excludes=[],
         win_no_prefer_redirects=False,
         win_private_assemblies=False,
         cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
         cipher=block_cipher)
exe = EXE(pyz,
      a.scripts,
      a.binaries,
      a.zipfiles,
      a.datas,
      name='TripCalc',
      debug=False,
      strip=False,
      upx=True,
      console=False , 
icon='C:\\Users\\test\\Downloads\\TripApp\\Benny.ico')

I tried adding the files beside datas:

('Benny.ico', 'C:\\Users\\test\\Downloads\\TripApp\\BennySM.ico', 'data', 'BgSM.gif', 'C:\\Users\\test\\Downloads\\TripApp\\BgSM.gif', 'data')

But it would not build with the ValueError: too many values to unpack (expected 2).

I followed the example from this post on how to add the file path to the main python file. Bundling data files with PyInstaller --onefile

I am able to build the exe and run it with the images commented out. Any help would be much appreciated.

When I get the Value Error message I setup the spec file with the following:

block_cipher = None

a = Analysis(['TripCalc.py'],
         pathex=['C:\\Users\\test\\Downloads\\TripApp'],
         binaries=[],
         datas=[('Benny.ico','C:\\Users\\test\\Downloads\\TripApp\\BennySM.ico','data','BgSM.gif','C:\\Users\\test\\Downloads\\TripApp\\BgSM.gif','data')],
         hiddenimports=[],
         hookspath=[],
         runtime_hooks=[],
         excludes=[],
         win_no_prefer_redirects=False,
         win_private_assemblies=False,
         cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
         cipher=block_cipher)
exe = EXE(pyz,
      a.scripts,
      a.binaries,
      a.zipfiles,
      a.datas,
      name='TripCalc',
      debug=False,
      strip=False,
      upx=True,
      console=False , 
icon='C:\\Users\\test\\Downloads\\TripApp\\Benny.ico')

Error window

Build -Value Error

With those changes to the spec file everything builds but the failed to launch script pops up when launching the exe. If they got packed with the exe they should be locationed in the temp file in app data correct?

Thanks!

Upvotes: 3

Views: 3018

Answers (2)

slightlynybbled
slightlynybbled

Reputation: 2645

In order to get around this for my own packages - which I try to make pip-installable - I have created a package that I'm calling stringify. The readme has the primary use case.

The idea of stringify is that you build your images (and other files types as well) into .py files which will be natively recognized by PyInstaller, requiring no _MEIPASS or if sys.frozen voodoo. Your spec files become more portable and are more likely to work out of the box.

Additionally, if you package your files up for distribution on pypi, then someone uses your images in their package, they don't have to do any spec file manipulation.... it just works!

Within setup.py - or sometime before you distribute your package:

from stringify import stringify_py

stringify_py('images', 'my_package/images.py')

You can then import your images and replace your calls to tkinter.PhotoImage like so:

from images import img

# tkinter.PhotoImage(file='/path/to/img.png')  # <- your original call
tkinter.PhotoImage(data=img)  # <- new call

For an example of this method, you might reference my tk_tools package. Have a look at setup.py and in tk_tools/visual.py. Note how the images are also stored within tk_tools/images.py, which is imported and used directly. PyInstaller will pick these up directly with the 'standard' spec file, reducing your mind share at build-time.

Upvotes: 2

Stephen Rauch
Stephen Rauch

Reputation: 49784

From the (DOCS):

Adding Data Files:

To have data files included in the bundle, provide a list that describes the files as the value of the datas= argument to Analysis. The list of data files is a list of tuples. Each tuple has two values, both of which must be strings:

The first string specifies the file or files as they are in this system now. The second specifies the name of the folder to contain the files at run-time.

So your datas line will need to be something like:

datas=[
    ('C:\\Users\\test\\Downloads\\TripApp\\BennySM.ico', 'data'),
    ('C:\\Users\\test\\Downloads\\TripApp\\BgSM.gif', 'data'),
],

Upvotes: 4

Related Questions