将Pyinstaller --onefile exe外部的配置文件添加到dist目录中

时间:2017-12-16 21:21:43

标签: python pyinstaller

情况

我在Windows上使用Pyinstaller制作我项目的.exe文件。

我想使用--onefile选项来获得干净的结果和易于分发的文件/程序。

我的程序使用config.ini文件存储配置选项。该文件可由用户自定义。

问题

使用--onefile选项Pyinstaller将所有声明的“data-file”放在单个.exe文件文件中。

我已经看到了这个request,但它给出了在一个文件内添加一个包文件而不是在外面,在.exe的同一级别和相同的dist目录。

在某些时候我曾想过在.spec文件中使用shutil.copy命令复制这个文件......但我认为是错误的。

有人可以帮助我吗?我会很感激: - )

2 个答案:

答案 0 :(得分:6)

A repository on Github帮助我找到了解决问题的方法。

我已使用shutil模块和.spec文件使用Pyinstaller config-sample.ini选项将额外数据文件(在我的情况下为--onefile文件)添加到dist文件夹。

为pyinstaller

创建.spec文件

首先,我使用我需要的选项创建了一个makepec文件:

$ pyi-makespec --onefile --windowed --name exefilename scriptname.py

此命令创建一个用于Pyinstaller

exefilename.spec文件

修改exefilename.spec添加shutil.copyfile

现在我已经编辑了exefilename.spec在文件末尾添加以下代码。

import shutil
shutil.copyfile('config-sample.ini', '{0}/config-sample.ini'.format(DISTPATH))
shutil.copyfile('whateveryouwant.ext', '{0}/whateveryouwant.ext'.format(DISTPATH))

此代码复制编译过程结束时所需的数据文件。 您可以使用shutil包中的所有可用方法。

运行PyInstaller

最后一步是运行编译过程

pyinstaller --clean exefilename.spec

结果是,在dist文件夹中,您应该将已编译的.exe文件与复制的数据文件一起使用。

考虑

在Pyinstaller的官方文档中,我没有找到获得此结果的选项。我认为它可以被视为一种解决方法......有效。

答案 1 :(得分:0)

我的解决方案类似于@ Stefano-Giraldi的出色解决方案。将目录传递到shutil.copyfile时,我的权限被拒绝。

我最终使用了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):
        shutil.rmtree(to_path)
    shutil.copytree(tup[0], os.path.join(DISTPATH, tup[1]) )

#### ... 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 )

这可以避免_MEI文件夹,并避免复制所需的配置文件到dist文件夹而不是temp文件夹中。

希望有帮助。