用pyinstaller打包,生成单个的exe程序,找不到资源文件怎么办?

被这个问题生生搅了两个月。
 
那还是在3月底的时候,我们这个程序啊,并不是BS架构的。写好之后,肯定不能把一堆py源码发给客户嘛,要使用pyinstaller打包的,做成一个exe的可执行程序。
pyinstaller怎么使用我就不教了,这个不是今天想说的重点,而且网上的教程还是很全面的。
 
我想说的是,如果你在程序中打开文件,并且使用相对路径的话,用pyinstaller打包成单个的exe文件(指加上了-F选项),之后你直接用exe程序来找,是找不到文件的。
 
原因是:这个单个的exe程序,在执行的时候,会先解压出一堆运行环境,放在C盘临时文件目录下生成的一个_MEIxxxxx的文件夹(xxxxx是随机数字)中,而程序默认的根路径,正是这个目录。因此我们的程序在打开相对路径的文件时,也是从这个目录查起。结果当然就是找不到文件。
 
对于这个问题的解决方法,网上通常是有两种:一种是,将文件一起打包进exe文件中,也就是在pyinstaller打包时命令加上 --add-data 选项。另一种是,在程序中用代码找到当前执行的临时目录,然后以此为起点去找程序中调用的目录。
 
 
但是两种方法对我这来说都不是很合适。我这边会通过程序写一些文件,如果这次退出程序,下次一样找不到这些文件。于是,两个月以来,我使用的方法都是:直接写绝对路径。我知道这种方法不是很好,但实在也是无奈。
 
直到我无意中看到了这篇文章:
才知道事情居然如此简单。
 
我们都知道,一个python程序,如果在命令行执行时,是这样的:
 
python some_python_code.py arg1 arg2 arg3  
 
如果在代码中想接收这些参数,可以使用sys模块:
 
import sys
print(sys.argv)

 

可以看到这个结果是一个列表:
 
["some_python_code.py", "arg1", "arg2", "arg3"]

 

但是,如果我们打包的exe程序在执行时,sys.argv[0] 显示的是这个exe的名称。如果再用 os.path.abspath(sys.argv[0]) 的话,得到的就是exe所在位置的绝对路径了。再进一步,
 
BASE_DIR = os.path.dirname(os.path.abspath(sys.argv[0]))

 

那么BASE_DIR的结果就是exe所在的目录了。这正是我想要的结果,这样的话,我就可以把exe程序放在任意目录,而资源文件的读写也可以使用相对路径来读到了。 
 
posted @ 2024-05-14 16:04  _小苹果  阅读(888)  评论(0编辑  收藏  举报