首先加入3个库的钩子 hook
hook-Orange
from PyInstaller.utils.hooks import copy_metadata
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import collect_submodules
from PyInstaller.utils.hooks import collect_all
datas, binaries, hiddenimports = collect_all("Orange")
datas += copy_metadata('Orange3')
# datas += collect_data_files("Orange")
# hiddenimports = collect_submodules('Orange')
hook-orangecanvas
from PyInstaller.utils.hooks import copy_metadata
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import collect_submodules
from PyInstaller.utils.hooks import collect_all
datas, binaries, hiddenimports = collect_all("orangecanvas")
datas += copy_metadata('orange_canvas_core')
# datas += collect_data_files("orangecanvas")
# hiddenimports = collect_submodules('orangecanvas')
hook-orangewidget
from PyInstaller.utils.hooks import copy_metadata
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import collect_submodules
from PyInstaller.utils.hooks import collect_all
datas, binaries, hiddenimports = collect_all("orangewidget")
datas += copy_metadata('orange_widget_base')
# datas += collect_data_files("orangewidget")
# hiddenimports = collect_submodules('orangewidget')
保证不缺文件
改动入口文件 Orange3/canvas/__main__
def resource_path(relative_path):
if getattr(sys, 'frozen', False): # 是否Bundle Resource
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
解决临时temp位置读取问题
539行
if pkg_resources.resource_exists(pkg_name, resource):
开始,打包后pkg_resources功能使用有错误,需要修改为手动读取
with open(resource_path(pkg_name + '/' + resource)) as f:
stylesheet_string = f.read()
base = resource_path(os.getcwd() + '\\' + pkg_name + '\\' + "styles")
pattern = re.compile(
r"^\s@([a-zA-Z0-9_]+?)\s*:\s*([a-zA-Z0-9_/]+?);\s*$",
flags=re.MULTILINE
)
matches = pattern.findall(stylesheet_string)
for prefix, search_path in matches:
QDir.addSearchPath(prefix, os.path.join(base, search_path))
log.info("Adding search path %r for prefix, %r",
search_path, prefix)
stylesheet_string = pattern.sub("", stylesheet_string)
dirpath = resource_path(os.getcwd() + '\\' + pkg_name)
QDir.addSearchPath("canvas_icons", os.path.join(dirpath, "icons"))
然后spec打包配置文件需要修改,解决剩余问题
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
import pkg_resources
import os
hook_ep_packages = dict()
hiddenimports = set()
# List of packages that should have there Distutils entrypoints included.
ep_packages = ["orange.widgets"]
if ep_packages:
for ep_package in ep_packages:
for ep in pkg_resources.iter_entry_points(ep_package):
if ep_package in hook_ep_packages:
package_entry_point = hook_ep_packages[ep_package]
else:
package_entry_point = []
hook_ep_packages[ep_package] = package_entry_point
package_entry_point.append("{} = {}".format(ep.name, ep.module_name))
hiddenimports.add(ep.module_name)
try:
os.mkdir('./generated')
except FileExistsError:
pass
解决pkg_resources.iter_entry_points问题,生成在线运行钩子文件
with open("./generated/pkg_resources_hook.py", "w") as f:
f.write("""# Runtime hook generated from spec file to support pkg_resources entrypoints.
ep_packages = {}
if ep_packages:
import pkg_resources
default_iter_entry_points = pkg_resources.iter_entry_points
def hook_iter_entry_points(group, name=None):
if group in ep_packages and ep_packages[group]:
eps = ep_packages[group]
for ep in eps:
parsedEp = pkg_resources.EntryPoint.parse(ep)
parsedEp.dist = pkg_resources.Distribution(project_name='Orange3',version='3.27.1')
yield parsedEp
else:
return default_iter_entry_points(group, name)
pkg_resources.iter_entry_points = hook_iter_entry_points
""".format(hook_ep_packages))
a = Analysis(['run.py'],
pathex=['C:\\Users\\Lenovo\\PycharmProjects\\pythonProject'],
binaries=[],
datas=[],
hiddenimports=list(hiddenimports)+['sklearn.utils._weight_vector','openTSNE._matrix_mul.matrix_mul'],解决部分组件缺失包问题
hookspath=[],
runtime_hooks=["./generated/pkg_resources_hook.py"],在线运行钩子文件
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
remove = ["_simple_tree", "_tree_scorers", "_contingency", "_io", "_valuecount", "_variable", "_distance", "_discretize", "_relieff", "_som", "_grid_density"]
temp=a.binaries[:]
for t in temp:
if any(r+'.cp37-win_amd64.pyd' in t[1] for r in remove):
print('Removing'+ t[1])
a.binaries.remove(t)移除无效pyd文件,解决运行前warning提示对话框问题
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='run',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False , icon='favicon.ico')加入打包程序图标
本文介绍如何使用PyInstaller工具对Python项目进行打包,包括定制hook文件、处理资源路径、解决依赖库问题等关键技术点。
1万+

被折叠的 条评论
为什么被折叠?



