所谓冻结“Freezing“,指的是将Python程序编译,并将其和Python解释器一起其他的资源文件整合打包到一起,形成一个可以独立运行的程序。这样用户在接收到这个程序包的时候可以开箱即用,不需要安装额外的依赖。就像超市里面的熟食那样方便,买回家可以直接食用。

The Hichhiker’s Guide to Python里面的一章Freezing Your Code专门讲了几种冻结代码的工具,比如:bbFreeze、py2exe、pyInstaller、cx_Freeze、py2app等。这篇文章以pyInstaller为例,介绍怎么冻结一个基于pywebview的程序。

本文默认使用Python 3,而不是Python 2。

准备一个用来Freeze的Python程序

我们准备用pywebview来准备一个用来freeze的Python程序。pywebview基于平台自身WebView控件,可以用来制作具有一定功能的跨平台GUI程序。pywebview的原理也不复杂,它将每个平台的webview控件(这些控件是浏览器比如Windows的IE、macOS的Safari等的组成部分)用Python封装成统一的接口供其他程序调用。所以pywebview基本上可以看出:

 pywebview应用 = webview控件 + web前端(HTML/CSS/Javascript) + web后端(HTTP Server)【可选】

首先先来看一下一个简单的pywebview应用(没有web后端):

"""
文件: greetings.py
"""
import webview
import threading

def load_html():
    webview.load_html("<h1>Hello, world</h1>")

if __name__ == '__main__':
    t = threading.Thread(target=load_html)
    t.start()

    webview.create_window("Greetings!", width=480, height=320, resizable=True)

首先用pip安装pywebview: pip install pywebview。根据不同的平台,还需要将依赖装好。比如我是macOS,需要再安装cocoa。具体请看pywebview的安装说明

安装好pywebview以后,用python执行上面的greetings.py,就可以看到一个小图形窗口,上面显示Hello, world!

用pyInstaller来Freeze这个程序

首先安装pyInstallerpip install pyinstaller

pyInstaller使用起来非常简单,对着前面的greetings.py执行:pyinstaller greetings.py,pyInstaller会自动分析greetings.py,然后生成一下文件或者目录:

  • greetings.spec,pyInstaller的配置文件
  • buld/,pyInstaller的临时构建目录
  • dist/,pyInstaller的目标文件目录

我们进到dist目录下,可以看到里面存放着一个greetings子目录,打开发现里面有非常多的奇奇怪怪的文件。其他的不管,里面有一个和greetings文件夹同名的可执行文件,双击运行之后,我们前面熟悉的Hello, world!的图形窗口就出来了。

默认情况下,pyInstaller把要打包的程序当作是控制台程序,运行之后会跳出一个控制台窗口,显得不太美观(虽然对调试很有帮助,可以打印log)。可以用--windowed来指示pyInstaller生成一个图形界面程序,这样控制台就不会出现了。具体命令如下:pyinstaller --windowed greetings.py。 再macOS下,这个会直接在dist里面生成一个打包好的app,名字也叫做greetings,双击既可以运行之。

其他高级用法:打包成单个文件

pyInstaller的一个特色是可以把所有涉及到的程序➕数据打包成单一的文件,这样发放给用户的时候会比较简单,只需把单个文件交付就行了(当然,其他的工具比如Py2Exe也有类似功能)。

具体的操作是使用命令pyinstaller --onefile greetings.py来生成这个打包后的文件。

需要注意的是,就算打包成单个文件,当这个单个文件被执行的时候,里面的程序和数据会被解压到一个零时文件夹中。这个过程需要一定的时间,会导致启动过程变慢,幸好只需要解压一次而已。

其他高级用法:使用spec文件进行配置

前面有说过pyinstaller greetings.py会生成一个greetings.spec文件,这个文件记录各种选项。可以修改这个spec文件对生成打包文件的过程进行控制,具体可以参考文档Using Spec Files

调整完spec的配置之后,当需要生成打包文件的时候,可以用命令pyinstaller greetings.spec而不是pyinstaller greetings.py

(完)