【发布时间】:2016-05-17 03:25:14
【问题描述】:
我想为我的应用制作一个 Windows 包,其中大多数文件都在 .exe 中。根据Kivy - Create package on Windows,我安装了 setuptools 19.2。我在 Kivy 1.9.1 稳定版上。
根据https://kivy.org/docs/guide/packaging-windows.html 上的说明,我得到了以下 working .spec 文件:
from kivy.deps import sdl2, glew
# -*- mode: python -*-
block_cipher = None
a = Analysis(['..\\foo\\main.py'],
pathex=['path\\KO-exe'],
binaries=None,
datas=None,
hiddenimports=['six','packaging','packaging.version','webbrowser'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='foo',
debug=False,
strip=False,
upx=True,
console=True , icon='..\\foo\\ko.ico')
coll = COLLECT(exe, Tree('..\\foo\\'),
a.binaries,
a.zipfiles,
a.datas,
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins )],
strip=False,
upx=True,
name='foo')
但是,我最终得到一个包含许多文件的文件夹,而不是我可以分发给其他人的东西。因此,通过添加命令 --onefile 并将相同的步骤应用于 .spec 文件,我得到以下 NOT WORKING .spec:
# -*- mode: python -*-
from kivy.deps import sdl2, glew
block_cipher = None
a = Analysis(['..\\foo\\main.py'],
pathex=['path\\KO-exe'],
binaries=None,
datas=None,
hiddenimports=['six','packaging','packaging.version','webbrowser'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz, Tree('..\\foo\\'),
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins )],
name='foo',
debug=False,
strip=False,
upx=True,
console=True , icon='..\\foo\\ko.ico')
错误: .exe 仅在build 文件夹中而不在dist 中,运行时:Error loading Python DLL: C:\Users\user\AppData\Local\Temp\_MEI81162\python27.dll (error code 126)
问题
我一直在尝试将工作 .spec 和单个 .spec 进行各种组合(添加 COLLECT,移动 Tree('..\\foo\\')),但无济于事。
- 我应该改变什么才能拥有一个工作的单个 .exe?
- 如何选择要排除的文件/文件夹? (我应该在
Tree()中使用什么语法?) - 除了 data\db\database.db(在 .exe 中太慢)之外,我想要 .exe 中的几乎所有内容。我该怎么做?
编辑 3
在@tito 的帮助下工作的 .spec 文件:
from kivy.deps import sdl2, glew
# -*- mode: python -*-
#import pdb
import sys
sys.path += ["..\\foo\\"]
block_cipher = pyi_crypto.PyiBlockCipher(key='1234567890')
#'six','packaging','packaging.version',
a = Analysis(['..\\foo\\main.py'],
pathex=['D:\\path\\KO-exe'],
binaries=None,
datas=None,
hiddenimports=[
'webbrowser',
'__init__',
'data.__init__',
'data.screens.__init__',
'data.screens.dbmanager',
'data.screens.db_kv.__init__',
'data.screens.db_kv.backupsd',
],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
#pdb.set_trace()
# exclusion list
from os.path import join
from fnmatch import fnmatch
exclusion_patterns = (
join("kivy_install", "data", "images", "testpattern.png"),
join("kivy_install", "data", "images", "image-loading.gif"),
join("kivy_install", "data", "keyboards*"),
join("kivy_install", "data", "settings_kivy.json"),
join("kivy_install", "data", "logo*"),
join("kivy_install", "data", "fonts", "DejaVuSans*"),
join("kivy_install", "modules*"),
join("Include*"),
join("sdl2-config"),
# Filter app directory
join("personal*"),
join("sign-apk*"),
join(".idea*"),
)
def can_exclude(fn):
for pat in exclusion_patterns:
if fnmatch(fn, pat):
return True
a.datas = [x for x in a.datas if not can_exclude(x[0])]
a.binaries = [x for x in a.binaries if not can_exclude(x[0])]
# Filter app directory
appfolder = [x for x in Tree('..\\foo\\', excludes=['*.py','*.pyc']) if not can_exclude(x[0])]
#print(a.zipped_data)
#pdb.set_trace()
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='foo',
debug=True,
strip=False,
upx=True,
console=True , icon='..\\foo\\ko.ico')
coll = COLLECT(exe, appfolder,
a.binaries,
a.zipfiles,
a.datas,
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins )],
strip=False,
upx=True,
name='foo')
我想从我的应用程序文件夹中排除文件夹和文件,感谢tito,通过你我也想出了如何过滤Tree()。
让 PyInstaller 排除文件后,我将尝试在输出文件上运行 NSIS。
【问题讨论】:
-
对于带有 NSIS 的单 exe:stackoverflow.com/questions/35552659/…