I'm using Pyinstaller on Windows to make an .exe file of my project.
I would like to use --onefile
option to have a clean result and an easy to distribute file/program.
My program use a config.ini
file for storing config options. This file could be customized by users.
Using --onefile
option Pyinstaller put all declared "data-file" inside the single .exe
file file.
I've seen this request but it give istructions to add a bundle file inside the onefile and not outside, at the same level of the .exe
and in the same dist
directory.
At some point I've thought to use a shutil.copy command inside .spec file to copy this file... but I think to be in the wrong way.
Can some one help me? I'll appreciate it :-)
When we specify the onefile option, to the PyInstaller, it unpacks all the files to a TEMP directory, executes the file, and later discard the TEMP folder. When you specify the add-data option along with onefile, then you need to read the data referred to in the TEMP folder.
pip will install PyInstaller's dependencies along with a new command: pyinstaller . PyInstaller can be imported in your Python code and used as a library, but you'll likely only use it as a CLI tool. You'll use the library interface if you create your own hook files.
A repository on Github helped me to find a solution to my question.
I've used shutil
module and .spec
file to add extra data files (in my case a config-sample.ini
file) to dist folder using Pyinstaller --onefile
option.
First of all I've create a makespec file with the options I need:
$ pyi-makespec --onefile --windowed --name exefilename scriptname.py
This comand create an exefilename.spec
file to use with Pyinstaller
Now I've edited the exefilename.spec
adding at the end of the file the following code.
import shutil shutil.copyfile('config-sample.ini', '{0}/config-sample.ini'.format(DISTPATH)) shutil.copyfile('whateveryouwant.ext', '{0}/whateveryouwant.ext'.format(DISTPATH))
This code copy the data files needed at the end of compile process. You could use all the methods available in shutil
package.
The final step is to run compile process
pyinstaller --clean exefilename.spec
The result is that in the dist folder you should have the compiled .exe file together with the data files copied.
In the official documentation of Pyinstaller I didn't found an option to get this result. I think it could be considered as a workaround... that works.
My solution is similar to @Stefano-Giraldi 's excellent solution. I was getting permission denied when passing directories to the shutil.copyfile
.
I ended up using shutil.copytree
:
import sys, os, shutil site_packages = os.path.join(os.path.dirname(sys.executable), "Lib", "site-packages") added_files = [ (os.path.join(site_packages, 'dash_html_components'), 'dash_html_components'), (os.path.join(site_packages, 'dash_core_components'), 'dash_core_components'), (os.path.join(site_packages, 'plotly'), 'plotly'), (os.path.join(site_packages, 'scipy', '.libs', '*.dll'), '.') ] working_dir_files = [ ('assets', 'assets'), ('csv', 'csv') ] print('ADDED FILES: (will show up in sys._MEIPASS)') print(added_files) print('Copying files to the dist folder') print(os.getcwd()) for tup in working_dir_files: print(tup) to_path = os.path.join(DISTPATH, tup[1]) if os.path.exists(to_path): if os.path.isdir(to_path): shutil.rmtree(to_path) else: os.remove(to_path) if os.path.isdir(tup[0]): shutil.copytree(tup[0], to_path ) else: shutil.copyfile(tup[0], to_path ) #### ... Rest of spec file a = Analysis(['myapp.py'], pathex=['.', os.path.join(site_packages, 'scipy', '.libs')], binaries=[], datas=added_files, hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='myapp', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True )
This avoids the _MEI folder and keeps it from copying config files that you want in your dist folder and not in a temp folder.
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With