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

2024-04-26 11:25:26 发布

您现在位置:Python中文网/ 问答频道 /正文

形势

我正在Windows上使用Pyinstaller为我的项目生成一个.exe文件。

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

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

问题

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

我见过这个request,但它给出了在onefile内部而不是外部,在.exe的同一级别和同一个dist目录中添加bundle文件的指令。

在某个时候,我想在.spec文件中使用shutil.copy命令来复制这个文件。。。但我认为我走错了路。

有人能帮我吗?我会很感激的:-)


Tags: 文件项目用户程序config声明windows数据文件
2条回答

我的解决方案类似于@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):
                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 )

这样可以避免使用“妹妹”文件夹,并防止它复制您希望在dist文件夹而不是临时文件夹中的配置文件。

希望能有所帮助。

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

我使用了shutil模块和.spec文件来添加额外的数据文件(在我的例子中是config-sample.ini文件)来使用Pyinstaller--onefile选项来分配文件夹。

为pyinstaller

创建一个.spec文件

首先,我创建了一个makespec文件,其中包含我需要的选项:

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

此命令创建一个与Pyinstaller一起使用的exefilename.spec文件

修改exefilename.spec添加shuil.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的官方文档中,我没有找到获得此结果的选项。我认为这可以被看作是一种解决办法。。。那很有效。

相关问题 更多 >