一些模块移动位置后的兼容性优化
下面以gooey模块举例: 用于命令行UI可视化的gooey模块,该模块内部代码使用的sys._MEIPASS还默认根目录作为模块存放目录来工作,所以此种模块还需要整体不移动位置,同时该模块不能添加到excludes里面,否则会分析时漏掉一些py文件,导致软件不能正常运转。 我已经按照你的思路完善了一下解决了这个问题,但是不知道该怎么提交。
我测试了一下,确实如你所说。这几天没有空,过上一到两个礼拜,我把这个东西更新上。
另外,Pyinstaller 最近新增了一个提交 https://github.com/pyinstaller/pyinstaller/pull/7713 ,是关于原生实现这个模式(把杂七杂八东西都打包到一个文件夹里)的,已经代码实现了。不过现在应该是开发状态,还没推送到正式版分支中,你可以去看一下。
sys._MEIPASS是一个在 PyInstaller 打包的可执行文件中自动生成的变量。它是一个指向临时解压缩目录的路径,其中包含了打包的应用程序和相关资源文件。当使用 PyInstaller 将 Python 程序打包成可执行文件时,程序和其依赖的资源文件将被捆绑在一起,并被压缩到一个临时的目录中。
sys._MEIPASS就是指向这个临时目录的路径。在运行打包后的可执行文件时,程序可以通过
sys._MEIPASS变量来访问打包后的资源文件。这对于加载依赖文件、配置文件或其他资源文件非常有用,因为打包后的可执行文件与原始的 Python 源代码的目录结构可能有所不同。请注意,
sys._MEIPASS是一个内部变量,并且不在 Python 的标准库中定义。它由 PyInstaller 自动生成并提供给应用程序使用。
然后我又测试了一下,既然 gooey 使用 sys._MEIPASS 作为模块目录,那我在 hook.py 中把这个变量修改到 libs 文件夹里面不就行了吗。我这边测试是成功了的。
你把 hook.py 内容改成这个试一试:
import sys
from pathlib import Path
BASE_DIR = Path(__file__).parent
sys._MEIPASS= str(BASE_DIR / 'libs')
# 为所有已存在于 sys.path 中的路径都插入 libs ,加到 sys.path 中
# 让程序到 libs 文件夹查找依赖
for p in sys.path.copy():
relative_p = Path(p).relative_to(BASE_DIR)
new_p = BASE_DIR / 'libs' / relative_p
sys.path.insert(0, str(new_p))
sys.path.insert(0, str(BASE_DIR)) # 把运行文件所在的根目录排到第一位,优先从根目录查找依赖包
嗯嗯,修改的hook文件可以了,感觉也完美多了,避免哪些模块也有这种暗雷。 还得是作者你啊,一针见血解决了问题。 我最初是想增加通过增加不移动的模块来实现的,还想着好扩展呢,如下面的示例:
# 以 (src, dest) 元组的形式添加到 datas 列表
datas = []
# 不进行移动的的模块
immovable_modules = ["gooey"]
immovable_module_dirs=[]
for m in immovable_modules:
if not find_spec(m): continue
module_dir = dirname(find_spec(m).origin)
immovable_module_dirs.append(module_dir)
# 把 a.datas 中不属于自定义的文件重定向到 libs 文件夹
temp = a.datas.copy(); a.datas.clear()
for dst, src, type in temp:
c1 = (dst == 'base_library.zip') # 判断文件是否为 base_library.zip
c2 = any([dst.startswith(f) for f in my_folders]) # 判断文件是否属于 my_folders
c3 = any([dst.startswith(f) for f in my_files]) # 判断文件是否属于 my_files
c4 = any(src.startswith(f) for f in immovable_module_dirs) #判断文件是否属于 immovable_modules
if any([c1, c2, c3,c4]):
a.datas.append((dst, src, type))
好久没用 pyinstaller,今天一看,都已经更新到 6.2 了,自从 6.0 开始,默认打包都会把杂七杂八文件放入一个子文件夹了!