Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pyinstaller not picking up Tree or Data files

I'm trying to build a very basic python script with pyinstaller: print 'hello world!' and I'm trying to make a data file OR a directory of data files available to the binary.

I've read the documentation over and over, I've tried building with 1.5, 2.0, and the dev build of 2.0, I've tried building with --onefile AND --onedir, I've tried building on OS X and Linux, but for some reason the datafile/tree statements in my .spec file seem to be ignored.

Here are some .spec file variations I've tried:

coll = COLLECT(exe,
               a.binaries
               [('README','/Users/username/my_little_app/foo','DATA')],
               Tree('/Users/username/my_little_app/foo','foo'),
               Tree('/foo','foo'),
               Tree('my_little_app/foo','foo'),
               [('my_xml_file.xml','my_little_app/partner.xml','DATA')],
               a.zipfiles,
               a.datas,
               strip=None,
               upx=True,
               name=os.path.join('dist', 'my_little_app'))


a.datas += [('my_xml_file.xml', '/Users/username/my_little_app/my_xml_file.xml',  'DATA')]

Is there something I'm missing??

like image 715
Joseph Ferraro Avatar asked Feb 07 '13 19:02

Joseph Ferraro


1 Answers

This answer is pretty late, but the way to add arbitrary files to a PyInstaller build is pretty clearly documented:

https://pyinstaller.readthedocs.io/en/stable/spec-files.html#adding-files-to-the-bundle

The first string in the tuple is the path to the file, the second string is the path it will have under the built package. In other words, your last line should read like this:

a.datas += [("/path/to/my_xml_file.xml", "my_xml_file.xml")]

You can also add full directories like this:

a.datas += [("/path/to/dir", "dir")]

I've added the relevant part of the docs below.


Adding Files to the Bundle

To add files to the bundle, you create a list that describes the files and supply it to the Analysis call.

Adding Data Files

You 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 names of the files in the bundled app at run-time.

For example, to add a single README file to a one-folder app, you could modify the spec file as follows:

a = Analysis(...
     datas=[ ('src/README.txt', 'README') ],
     hiddenimports=...
     )

You have made the datas= argument a one-item list. The item is a tuple in which the first string says the existing file is src/README.txt. This file will be copied into the bundle with name README.

The spec file is more readable if you create the list of added files in a separate statement:

added_files = [
     ( 'src/README.txt', 'README' )
     ]
a = Analysis(...
     datas= added_files,
     ...
     )

The strings may use either / or \ as the path separator character. You can specify input files using "glob" abbreviations. When the input is multiple files, the output string may be the name of a folder. For example to include all the .mp3 files from a certain folder:

added_files = [
         ( '/mygame/sfx/*.mp3', 'sfx' ),
         ( 'src/README.txt', 'README' )
         ]

All files matching /mygame/sfx/*.mp3 will be copied into the bundle and stored in a folder named sfx.

The path to the input file or folder may be absolute as in the first tuple, or relative as in the second. When it is relative, it is taken as relative to the location of the spec file.

You can also include the entire contents of a folder:

added_files = [
         ( '/mygame/data', 'data' ),
         ( '/mygame/sfx/*.mp3', 'sfx' ),
         ( 'src/README.txt', 'README' )
         ]

All files in /mygame/data will be copied recursively into a folder named data in the bundle.

like image 52
Hubro Avatar answered Oct 14 '22 08:10

Hubro