Honker.org.cn红盟网讯 写完python代码后想发给女神炫耀时,发现女神电脑没有python运行环境,怎么办?pyinstaller可以将python代码打包成exe文件。exe文件不依赖于python环境,双击即可在女神电脑上运行。 一、pyinstaller介绍 pyinstaller是一个第三方模块,专用于python代码的exe打包。虽然python提供了多种方法进行exe打包,但是pyinstaller打包最强大而且好用。 二、pyinstaller安装 通过pip进行安装: 安装完成后,验证是否成功安装: 三、pyinstaller打包 这里以一个自己写的GUI程序(angry_it_man.py)作为例子向大家讲解pyinstaller是如何把python代码打包成exe文件的。 angry_it_man.py使用TKinter实现GUI,其中引用到favicon.ico图标文件和image.png文件,这俩资源文件都存放在当前目录的assets文件夹中,源码如下: import tkinter as tk window = tk.Tk() window.title('愤怒的it男') window.iconbitmap('assets/favicon.ico') window.geometry('450x300') canvas = tk.Canvas(window, bg='grey') img = tk.PhotoImage(file='assets/image.png') canvas.create_image(30, 60, image=img, anchor='nw') canvas.create_text(200, 70, fill='white', text='愤怒的it男', font=('宋体',10,'bold'), anchor='nw') point = [(200,200),(220,190),(240,170),(260,180),(280,150),(300,140),(320,160),(340,150),(360,130)] canvas.create_line(point, fill='white', dash=(1,1), arrow=tk.LAST, width=3) canvas.pack() window.mainloop() |
angry_it_man.py运行后GUI界面如下: 将其打包成exe文件很简单,只需一行命令: pyinstaller angry_it_man.py |
打包完成后,当前目录下生成了build和dist文件夹,以及一个spec文件。dist文件夹包含打包的结果,build文件夹中是一些日志信息,而spec文件用于打包的配置信息。 重点来了,由于打包时没有绑定任何的资源文件,所以此时运行时会一闪而过,打不开!怎么办呢? 1、参数--add-data 打包时使用参数--add-data,可将资源文件一起打包进去。因此上面的打包命令可改为: pyinstaller --add-data assets;assets angry_it_man.py |
2、参数-w 使用上面一条打包命令生成的exe文件已经可以正常打开了,但是每次打开都会伴随着一个黑屏窗口打开,这个黑屏窗口其实是用来debug的,通过它可以打印程序运行时的错误。如果不想要,上面的打包命令可改为: pyinstaller --add-data assets;assets -w angry_it_man.py |
3、参数-F 到这里已经非常OK了,美中不足的是打包后生成的是一个dist文件夹。经常需要复制文件夹不仅麻烦,而且还无法防止里面的内容被用户修改。因此,我们可以使用参数-F,把所有的东西都打包进单个的exe文件中: pyinstaller --add-data assets;assets -w -F angry_it_man.py |
4、参数-i 上面一条打包命令后,确实在dist文件中生成一个单独的exe文件,但是打开后报错了,说是没找到ico图标文件。 这是因为pyinstaller单文件模式下打包的exe文件,在启动后会将assets资源文件夹放到一个临时文件夹中,而不是原来的当前目录了。这个临时文件夹的名字不是固定的,叫做_MEIxxxxx,其中xxxxx是随机数。这个临时文件夹的路径在打包后会被放到sys._MEIPASS这个变量里面,只需要调用sys._MEIPASS就可以获得这个文件夹的路径。 于是,我们可以通过以下函数返回正确的路径: def get_path(relative_path): try: base_path = sys._MEIPASS # pyinstaller打包后的路径 except AttributeError: base_path = os.path.abspath(".") # 当前工作目录的路径 return os.path.normpath(os.path.join(base_path, relative_path)) # 返回实际路径 |
因此,我们可以修改源码如下: import tkinter as tk import sys import os def get_path(relative_path): try: base_path = sys._MEIPASS except AttributeError: base_path = os.path.abspath(".") return os.path.normpath(os.path.join(base_path, relative_path)) window = tk.Tk() window.title('愤怒的it男') window.iconbitmap(get_path('assets/favicon.ico')) window.geometry('450x300') canvas = tk.Canvas(window, bg='grey') img = tk.PhotoImage(file=get_path('assets/image.png')) canvas.create_image(30, 60, image=img, anchor='nw') canvas.create_text(200, 70, fill='white', text='愤怒的it男', font=('宋体',10,'bold'), anchor='nw') point = [(200,200),(220,190),(240,170),(260,180),(280,150),(300,140),(320,160),(340,150),(360,130)] canvas.create_line(point, fill='white', dash=(1,1), arrow=tk.LAST, width=3) canvas.pack() window.mainloop() |
然后打包命令加入参数-i,打包: pyinstaller --add-data assets;assets -i assets\favicon.ico -w -F angry_it_man.py |
5、参数-n 很好,这下已经可以打包出能够成功运行的单个exe文件了。如果我想自定义打包生成的exe文件名怎么办呢?可以在打包命令中加入参数-n pyinstaller --add-data assets;assets -i assets\favicon.ico -w -F angry_it_man.py -n 愤怒的it男 |
6、参数--key 其实打包出来的exe文件是很不安全的,分分钟被反编译破解,破解步骤如下: a.先使用pyinstxtractor包,提取生成的exe中的pyz(一般是pyc)文件 # 安装:直接执行下载的 py 文件即可 # 解包 xx.exe python pyinstxtractor.py xx.exe |
执行命令后会生成xx.exe_extracted文件夹,xxx.exe.manifest文件等。再找到一个没有后缀名的文件,就是打包的.py文件对应的pyc b.然后再使用python-uncompyle6工具,将pyc文件反编成.py文件 # 安装 pip install uncompyle6 |
# 反编译 xxx.pyc 文件,输出为 xxx.py 源码文件 uncompyle6 -o xxx.py xxx.pyc |
如果你不想自己的源码泄露怎么办呢?其实pyinstaller也是支持加密打包的,使用参数--key即可,例如: pyinstaller --add-data assets;assets -i assets\favicon.ico -w -F --key 4444 angry_it_man.py -n 愤怒的it男 |
虽然说这种加密的安全性也不是很强,但已经可以把绝大多数的半吊子程序员拒之门外了。 五、pyinstaller参数详解 参数 | 解释 | -D | 文件夹模式。在打包完成后生成一个文件夹,其中包含一个exe文件和若干依赖文件。(默认) | -W | 单文件模式。在打包完成后只会生成一个单独的exe文件。 | --add-data <SRC:DEST or SRC:DEST> | 指定一个文件夹或文件(非二进制),将其嵌入到exe中。 | --add-binary <SRC;DEST or SRC:DEST> | 和--add-data类似,不过指定的文件夹或文件是二进制的 | -p DIR --paths DIR | 提供一个路径进行搜索并且导入里面的模块,这可以解决有时候第三方模块找不到的问题。 (不同的路径使用路径分隔符os.pathsep分隔开,或者多次使用这个参数) | --hidden-import MODULENAME --hiddenimport MODULENAME | 需要进行额外导入的模块。(这个参数可以多次使用,可以解决一些模块找不到的问题) 当pyinstaller在程序中找不到一些模块时,需要你额外指定。 | --splash IMAGE_FILE | 添加一个启动画面(图片文件)路径,在程序运行前显示指定的启动图片,起到加载提示的效果。 | -c, --console,--nowindowed | 打包程序运行后出现一个黑色的控制台窗口(默认) | -w, --windowed,--noconsole | 打包程序运行后隐藏控制台窗口 | -i <FILE.ico or FILE. exe, ID or FILE.icns or Inage or "NONE”> --icon <FILE.ico or FILE.exe, ID or FILE.icns or Image or "NONE"> | 设置打包后exe程序的图标(只能在Windows和macOS上使用) | --disable-windowed-traceback | 禁用异常提示(只能在Windows和macOS上使用) | -h,--help | 打印pyinstaller的帮助信息 | -v,--version | 打印pyinstaller的版本信息 |
六、参考引用 https://pyinstaller.org/ http://t.csdnimg.cn/CrJfr https://zhuanlan.zhihu.com/p/470301078?utm_psn=1720785848621035520 |