捐助郴维网
感谢您对郴维网的支持,你的支持将是郴维网持续发展的动力!
二维码
×
当前位置:郴维网 >扩展阅读 > 正文
6 2021.11

PyInstaller打包exe

点击次数:27 更新时间:2021-11-6 22:39:37  【打印此页

一:安装

注:安装pyinstaller前,先安装几个Python模块 pypiwin32,pywin32 和 pefile 包

直接使用使用pip安装:

  pip install pypiwin32

  pip install pywin32

  pip install pefile

 

安装PyInstaller

  方法一:直接使用pip

    pip install pyinstaller

  方法二:下载源码安装

    下载页面:http://www.pyinstaller.org/downloads.html

    该页面有安装方法和源码包下载

 

  查看安装结果

   pyinstaller -v 或 pyinstaller --version

    

 

二:打包exe

相关参数

pyinstaller 参数 test.py

-D (-onedir); 创建一个目录,包含exe文件,但会依赖很多文件(默认选项)。

-c (-console, –nowindowed); 使用控制台,无界面(默认)

-F (-onefile); 打包成一个exe文件

-w (-windowed, –noconsole); 使用窗口,无控制台

-F -i 图标名称.ico test.py; 可为exe文件生成图标。

-upx (--upx-dir UPX_DIR); 压缩生成的exe文件(使用后可能会提vcruntime140.dll错误或其它莫名奇妙的问题)

--add-data; 打包额外资源

--add-binary;打包额外的代码

 

-upx

1. 下载upx:

  地址:http://upx.sourceforge.net/

2. 把upx解压到要转换到的py文件目录下

3. pyinstaller参数中添加upx路径

  pyinstaller -F test.py --upx-dir upx391w 注:upx391w 为upx文件夹

 

--add-data

pyinstaller -F test.py -add-data=src;dest windows以 分割,linux以 分割

src 打包前资源文件路径或资源文件所在文件夹(相对test.py路径)

dest 打包后资源文件释放的文件夹(相对“临时文件夹”的路径,exe运行时会将所需的文件释放到Windows系统的临时文件夹中)

注:使用这个参数的功能也可用编辑.spec文件实现,可参考的“如何将资源文件一起打包至exe中”

 

--add-binary

和--add-data差不多。

与--add-data不同的是,用--add-binary添加的.py文件,pyinstaller会分析它引用的文件并把它们一同添加进来

 

简单示例

如:

cmd控制台定位到test.py所在目录,执行命令:

pyinstaller -F test.py

执行完成后会在test.py生成一些目录和文件,exe文件在dist目录中:

注:在执行pyinstaller编译时,建议先手动删除编译生成的文件 __pycache__、build、dist、 test.spec 等相关文件

效果:

其它复杂用法只需参考上面 "相关参数" 使用说明 添加参数即可。

 

三:其它

3.1 打包多进程程序

我们需要在main方法里,第一行加入如下代码:

multiprocessing.freeze_support()

代码:

import multiprocessing


if __name__ == '__main__':
    freeze_support() # main方法第一行必须先添加

 

3.2 如何将资源文件一起打包至exe中

要将资源文件打包进exe且正常调用资源文件进行使用,首先要知道2个知识点:

  1. pyinstaller打包后的exe是怎么工作的(简单理解)

  2. pyinstaller如何把资源文件打包进exe

 

1、打包后的exe是怎么工作的(简单理解)

打包后的exe运行时,会将脚本文件及一些所需要的文件释放到Windows的一个临时文件夹中。

如图:

 

如何在代码中获取到该临时文件夹的路径呢?

  程序可通过sys._MEIPASS访问临时文件夹中的资源

定义一个函数用于获取打包exe前后脚本所在路径:

# 获取资源文件所在路径(打包前和打包后路径是不一样的)
def resource_path(relative_path):
    if getattr(sys, 'frozen', False): # 是否Bundle Resource
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

 

2、如何把资源文件打包进exe

  有2种方法实现把资文件打包进exe,这2种方法其实都是一样,途径不同而已。

  a. 使用打包命令参数 --add-data

  b. 编辑.spec配置文件

 

  a. 使用打包命令参数 --add-data

    --add-data 打包额外资源

    如:

    pyinstaller -F test.py -add-data=src;dest windows以 ; 分割,linux以 : 分割

    src 打包前资源文件路径或资源文件所在文件夹(相对test.py路径)

    dest 打包后资源文件释放的文件夹(相对“临时文件夹”的路径,exe运行时会将所需的文件释放到Windows系统的临时文件夹中)

    使用该参数打包,执行命令后,打开test.spec配置文件,你会发现在datas项的值是[('src', 'dest')],所以该参数简化了修改配置文件的步骤。

  b. 编辑.spec配置文件

    b.1 首先使用Pyinstaller -F test.py打包,生成配置文件

      执行完后 删除build和dist文件夹,然后修改test.spec文件,如下图所示:

      

    b.2 把要打包的资源文件添加到pyinstaller配置文件中“.spec”

      编辑test.spec文件datas项,datas项中的元组功能参考如图:

      

      编辑好后,对test.spec文件进行编译:

      命令:pyinstaller -F test.spec

    b.3 实现案例

      构建一个简单程序:

      如图:

      

      test.py代码:

import os, sys

# 获取资源文件所在路径(打包前和打包后路径是不一样的)
def resource_path(relative_path):
    if getattr(sys, 'frozen', False): # 是否Bundle Resource
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

binDir = resource_path('')
aPath = resource_path(r'bin\a.txt')
bPath = resource_path(r'bin\b.txt')

print(binDir)
print(aPath)
print(bPath)
input()

 

    pyinstaller打包:

      命令:pyinstaller -F test.py --add-data=bin;bin

      运行效果:

      

 

3.3 替换tkinter左上角图标后,打包的exe执行失败

test.py 代码:

from tkinter import *

window = Tk()
window.title('测试')
window.iconbitmap('icon.ico')  # 加图标
window.mainloop()

打包exe前test.py正常运行,如图:

使用pyinstaller -F test.py打包的exe执行失败 如图:

 

解决办法

网上方法有很多种,我这提供的方法是把icon.ico以资源文件的形式打包进exe文件中。

取得icon.ico打包后所在路径

打包后的exe,运行exe后会把相关的文件释放到系统的临时文件夹中,这时我们只要取得该临时文件夹的路径即可得到icon.ico。

把icon.ico打包进exe中

取得icon.ico打包后所在路径

 

基本原理:Pyinstaller 可以将资源文件一起bundle到exe中,当exe在运行时,会生成一个临时文件夹,程序可通过sys._MEIPASS访问临时文件夹中的资源

 

定义一个函数,以获取打包前打包后脚本所在路径。

代码:

# 获取资源文件所在路径(打包前和打包后路径是不一样的)
def resource_path(relative_path):
    if getattr(sys, 'frozen', False): # 是否Bundle Resource
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

 

把icon.ico打包进exe中

命令:pyinstaller -F --add-data=icon.ico;. test.py

. 表示.py脚本所在路径

--add-data 打包额外资源

如:

  pyinstaller -F test.py -add-data=src;dest windows以 ; 分割,linux以 : 分割

  src 打包前资源文件路径或资源文件所在文件夹(相对test.py路径)

  dest 打包后资源文件释放的文件夹(相对“临时文件夹”的路径,exe运行时会将所需的文件释放到Windows系统的临时文件夹中)

  注:使用这个参数的功能也可用编辑.spec文件实现,可参考的“如何将资源文件一起打包至exe中”

 

实现代码

test.py代码:

from tkinter import *
import os, sys

# 获取资源文件所在路径(打包前和打包后路径是不一样的)
def resource_path(relative_path):
    if getattr(sys, 'frozen', False): # 是否Bundle Resource
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

iconPath = resource_path('icon.ico')

window = Tk()
window.title('测试')
window.iconbitmap(iconPath)  # 加图标
window.mainloop()

效果:

 

3.4 使用-w打包后,运行过程中还显示cmd窗口

解决办法:

  代码中调用命令或程序的模块换成subprocess模块

  subprocess模块目标是代替一些老的模块,比如os.system和os.spawn。

 

使用subprocess设置相应的参数即可。如:

subprocess.run(r'命令', shell=True, creationflags=0x08000000) # creationflags=0x08000000 隐藏cmd窗口
Tips
郴维网为您提供各类专业服务:
软件开发,电脑配件销售,WIFI路由器销售,上门电脑维修,上门安装系统,系统安装,软、硬件安装,电脑除尘清灰,显示器维修,WIFI安装调试,服务器维护,数据恢复,密码破解,网络布线,网络检修,打印机维修,打印机加碳粉,苹果电脑安装系统,苹果电脑安装双系统,监控安装维护,电脑外包,笔记本电脑维修,餐饮、美容行业软件安装 等。。。。。。
点击次数:27 更新时间:2021-11-6 22:39:37  【打印此页

上一条:Python赋值、切片、浅拷贝与深拷贝的区别

下一条:已经是最后一篇了

关键词推荐:郴州电脑城 郴州电脑维修公司 维修电脑公司 郴州软件开发 上门电脑维修 上门安装系统 笔记本电脑维修 郴州打印机维修 打印机加碳粉 电脑安装双系统 苹果电脑双系统 液晶显示器维修 联想笔记本维修 联想笔记本维修电话 戴尔笔记本维修电话 郴州戴尔笔记本维修 戴尔笔记本郴州维修点 华硕笔记本维修点 郴州华硕笔记本维修 郴州笔记本上网维修