Pyinstaller生成的EXE文件中__file__指向一个.py文件。

5
情境:我的Python脚本有一行代码,可以将自己复制到另一个目录。
该脚本具有将自己复制到其他位置的能力,这样可以在多个目录中同时运行该脚本。
shutil.copyfile(os.path.abspath(__file__), newPath)

问题:脚本编译成EXE文件并运行,但是出现以下错误提示:
FileNotFoundError: No such file or Directory: "C:\Path\To\EXE\script.py"

如您所见,EXE正在寻找未编译版本的.py文件(即自身版本)。
问题:是否有另一个Python命令可以让可执行文件找到自身而不是.py版本?
额外信息:我本来想尝试将.py替换为.exe并查看是否有效,但如果更改可执行文件的名称,则该程序将无法运行。
C:\ > script.exe
#Works as expected

C:\ > ren script.exe program.exe
C:\ > program.exe
FileNotFoundError: No such file or directory: "C:\script.py"
2个回答

11

我之前也遇到了这个问题。最后我在官方文档中找到了解决方法。


解决方法:

使用sys.argv[0]sys.executable来访问被执行文件的真实路径。


解释:

这是因为你的可执行文件处于一个bundle环境中,在这个环境中,所有的__file__常量都是相对于虚拟目录(实际上就是初始入口文件所在的目录)的相对路径。

根据文档的指示,你可以通过使用sys.argv[0]sys.executable来访问绝对路径,因为它们指向实际执行的命令。所以在bundle环境中,你调用script.exe,而sys.executable将会是script.exe。而在运行的生产环境中,你调用python script.pathsys.executable将会是python.exe


我最近也发现了这个问题,但是没有更新答案。不管怎样,还是谢谢! - Timothy Wong
我发现 sys.executable 只适用于 .exe 文件,但是当我像这样运行脚本 python script.py 并且将脚本构建为 exe 并使用 cmd 运行时,sys.argv[0] 有效。这是我现在引用事物的方式:os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), 'Resources') - ZiyadCodes

2
请尝试以下步骤:
from os.path import abspath, splitext
fromfile_without_ext, ext = splitext(abspath(__file__))
shutil.copyfile(fromfile_without_ext + '.exe', newPath)

(没有测试过,但应该可以运行...)

我会在有时间的时候尝试一下。谢谢。 - Timothy Wong
2
那不是正确的方法。因为__file__常量将始终是相对路径到入口脚本(例如script.py),无论您在何处以何种方式调用可执行文件。正确的方法是使用sys.argv[0]sys.executable - Cosmo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接