pyinstaller使用心得

使用方法

之前一直用的py2exe,到了python3.8不好用了,遂改为使用pyinstaller。使用下来,发现还是很好用的。

有两种模式:单文件和文件夹模式。

单文件模式是把所有东西都打包到一个exe里,执行的时候,解压到临时文件夹去执行,命令为:

pyinstaller --onefile my_script.py

windows下临时文件夹以_MEI打头,形如C:\Users\${user}\AppData\Local\Temp\_MEI1393882。

文件夹模式会生成一个文件夹,里面有exe+internal目录,internal目录里是exe所依赖的文件。命令为:

pyinstaller --onedir my_script.py

前者使用和发布更简单,一个exe搞定。但后者也有其作用,因为onefile模式下的exe对我们是黑盒,要了解exe内部子目录如何划分,可以查看onedir模式输出的internal目录。

常见问题

打包文件过大问题

解决该问题最有效的方法,是使用virtual env,跟python主环境隔离开,同时精简requirements.txt里的依赖,只放程序运行所必须的依赖。

资源文件无法访问的问题

要使用 --add-data选项,把运行过程中要访问的非python脚本资源打包进来,windows下,以onefile模式为例,我要把config/cfg1.json和config/cfg2.json打进exe的同层目录下,这么写:

pyinstaller --onefile --add-data "config/cfg1.json;config/" --add-data "config/cfg2.json;config/" my_script.py

可以看到,有多个–add-data选项,每个–add-data的值其实是一个pair,pair的第一项是源文件,可以是相对路径,pair的第二项是目标文件夹

如何区分pyinstaller打包后执行还是普通脚本执行

pyinstaller打包后执行和普通脚本方式执行,其工作目录是有区别的,这会影响资源文件的读取。

因pyinstaller打包时会设置sys.frozen和sys._MEIPASS字段,可使用如下脚本区分两种场景:

def is_pyinstaller_executable():
    # check sys.frozen
    if getattr(sys, 'frozen', False):
        return True
    # check sys.argv[0] 和 sys.executable
    if sys.argv[0] == sys.executable:
        return True
    # check sys._MEIPASS
    if getattr(sys, '_MEIPASS', None):
        return True
    return False


if is_pyinstaller_executable():
    print("run as a PyInstaller packaged executable")
    WORK_DIR = os.path.dirname(os.path.abspath(sys.executable))
else:
    print("run as normal py script")
    WORK_DIR = os.path.dirname(__file__)
print('working dir:%s' % WORK_DIR)

上述代码,在pyinstaller打包场景,获取exe所在目录为工作目录,而在普通脚本场景,则使用入口脚本my_script.py所在目录为工作目录。

顺带说一下,pyinstaller打包场景下,使用__file__方式获得的工作目录为解压的临时目录,就是前面提到的临时目录C:\Users\${user}\AppData\Local\Temp\_MEI1393882。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值