Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

一些模块移动位置后的兼容性优化 #2

Open
legendaryzp opened this issue Jul 16, 2023 · 4 comments
Open

一些模块移动位置后的兼容性优化 #2

legendaryzp opened this issue Jul 16, 2023 · 4 comments

Comments

@legendaryzp
Copy link

下面以gooey模块举例:
用于命令行UI可视化的gooey模块,该模块内部代码使用的sys._MEIPASS还默认根目录作为模块存放目录来工作,所以此种模块还需要整体不移动位置,同时该模块不能添加到excludes里面,否则会分析时漏掉一些py文件,导致软件不能正常运转。
我已经按照你的思路完善了一下解决了这个问题,但是不知道该怎么提交。

@HaujetZhao
Copy link
Owner

我测试了一下,确实如你所说。这几天没有空,过上一到两个礼拜,我把这个东西更新上。

另外,Pyinstaller 最近新增了一个提交 pyinstaller/pyinstaller#7713 ,是关于原生实现这个模式(把杂七杂八东西都打包到一个文件夹里)的,已经代码实现了。不过现在应该是开发状态,还没推送到正式版分支中,你可以去看一下。

@HaujetZhao
Copy link
Owner

HaujetZhao commented Jul 16, 2023

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))    # 把运行文件所在的根目录排到第一位,优先从根目录查找依赖包

@legendaryzp
Copy link
Author

嗯嗯,修改的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))

@HaujetZhao
Copy link
Owner

好久没用 pyinstaller,今天一看,都已经更新到 6.2 了,自从 6.0 开始,默认打包都会把杂七杂八文件放入一个子文件夹了!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants