WindowsでPyinstallerを使用して、プロジェクトの.exeファイルを作成しています。
--onefile
オプションを使用して、きれいな結果と簡単にファイル/プログラムを配布したいと思います。
私のプログラムは、設定オプションを格納するためにconfig.ini
ファイルを使用しています。このファイルはユーザーがカスタマイズできます。
--onefile
オプションを使用するPyinstallerは、宣言されたすべての「データファイル」を単一の.exe
ファイルファイル内に配置します。
私はこれを見た request だが、バンドルファイルを追加するように指示する onefile内 外ではなく、.exe
と同じレベルで、同じdist
ディレクトリにあります。
ある時点で、このファイルをコピーするために.specファイル内でshutil.copyコマンドを使用することを考えましたが、間違った方法だと思います。
誰か助けてもらえますか?感謝します:-)
Github上のリポジトリ は、私の質問に対する解決策を見つけるのに役立ちました。
shutil
モジュールと.spec
ファイルを使用して、Pyinstaller config-sample.ini
オプションを使用してdistフォルダーに追加のデータファイル(私の場合は--onefile
ファイル)を追加しました。
まず、必要なオプションを指定してmakespecファイルを作成します。
$ pyi-makespec --onefile --windowed --name exefilename scriptname.py
このコマンドは、Pyinstallerで使用するexefilename.spec
ファイルを作成します
これで、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 --clean exefilename.spec
その結果、distフォルダーには、コンパイルされた.exeファイルとコピーされたデータファイルが必要です。
Pyinstallerの公式ドキュメントでは、この結果を得るオプションが見つかりませんでした。私はそれが回避策と考えることができると思います...それはうまくいきます。
私の解決策は、@ 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 )
これにより、_MEIフォルダーが回避され、一時フォルダーではなくdistフォルダーに必要な構成ファイルがコピーされなくなります。
お役に立てば幸いです。