Python 高手编程系列一百五十:独立可执行文件

在介绍 Python 代码打包的材料中,创建独立可执行文件是经常被忽略的一个主题。这
主要是因为 Python 标准库中缺少合适的工具能够让程序员创建简单的可执行文件,用户不
需要安装 Python 解释器就可以运行这些可执行文件。
与 Python 相比,编译语言有一个很大的优点,就是它允许为给定的系统架构创建可执
行的应用程序,用户不需要知道底层技术就可以运行。Python 代码作为一个包分发时,需
要有 Python 解释器才能运行。这对于没有足够技术水平的用户来说造成了很大不便。
对开发者友好的操作系统(例如 Mac OS X 或大多数 Linux 发行版)都预装了 Python。
因此对于它们的用户来说,基于 Python 的应用仍然可以作为源代码包分发,依赖于主脚本
文件中特定的解释器指令(interpreter directive),这一指令通常被称为 shebang。对于大多数 Python 应用而言,其格式如下所示:
#!/usr/bin/env python
这种指令放在脚本的第一行,会将其标记为默认由指定环境的 Python 版本进行解释。
当然,它也可以采用更详细的形式,其中包括特定的 Python 版本,例如 python 3.4、
python 3 或 python 2。注意,这适用于大多数 POSIX 系统,但从定义来看并不是可移
植的。这种解决方案依赖于特定 Python 版本的存在,也依赖于/usr/bin/env 的 env 可
执行文件的可用性。在某些操作系统中,这两个假设可能都无法满足。此外,shebang 在
Windows 上也无法使用。另外,即使是有经验的开发人员,Windows 中 Python 环境的引导
也是一项挑战,所以你不能期望非技术用户能够自己完成。
另一件需要考虑的事情是桌面环境中简单的用户体验。用户通常期望,只通过单击就
可以从桌面运行应用程序。并不是所有桌面环境都支持将 Python 应用作为源代码分发。
因此,我们最好能够创建一个二进制发行版,其使用方法与其他任何编译的可执行文
件相同。幸运的是,可以创建一个可执行文件,里面同时嵌入了 Python 解释器和我们的项
目。这样用户无需考虑 Python 或其他依赖就可以打开我们的应用。
独立可执行文件何时有用
如果用户体验的简单性比用户与应用代码交互的能力更加重要,那么独立可执行文件
非常有用。注意,将应用作为可执行文件分发,只会使代码读取或修改更加困难 — 但不
是不可能。这不是保护应用代码的方法,而是应该作为使应用交互更加简单的方法。
独立可执行文件应该是对非技术最终用户分发应用的首选方式,也可能是分发
Windows 上的 Python 应用的唯一合理方式。
独立可执行文件通常适用于以下情形。
• 依赖于特定 Python 版本的应用,该版本在目标操作系统是可能不容易找到。
• 依赖于修改过的预编译 CPython 源代码的应用。
• 带有图形界面的应用。
• 具有许多用不同语言编写的二进制扩展的应用。
• 游戏。
常用工具
Python 没有任何内置库支持构建独立可执行文件。幸运的是,一些社区项目解决了这
一问题,并取得了不同程度的成功。其中最有名的 4 个是:
• PyInstaller;
• cx_Freeze;
• py2exe;
• py2app。
它们中的每一个在使用上都略有不同,每一个也都受到稍微不同的限制。在选择工具
之前,你需要确定面向哪些平台,因为每种打包工具仅支持特定的一些操作系统。
最好的情况是,在项目周期的最开始做出这样的决定。当然,所有这些工具都不需要
在代码中进行深入的交互,但如果你早期就开始构建独立包,那么你可以将整个过程自动
化,并节省未来的集成时间与成本。如果你将这件事放到以后,你可能会发现自己处于这
样的境地:项目构建得过于复杂,以致于所有可用的工具都无法使用。为这样的项目提供
独立可执行文件是有问题的,而且需要大量的时间。
PyInstaller
到目前为止,PyInstaller(http://www.pyinstaller.org/)是将 Python 包冻结为独立可执行
文件的最先进的程序。它在目前每种可用的解决方案中提供最广泛的多平台兼容性,所以
它也是最受推荐的方法。PyInstaller 支持的平台包括:
• Windows(32 位和 64 位);
• Linux(32 位和 64 位);
• Mac OS X(32 位和 64 位);
• FreeBSD、Solaris 和 AIX。
支持的 Python 版本包括 Python 2.7 与 Python 3.3、3.4 和 3.5。它可以在 PyPI 上找到,
所以可以利用 pip 在工作环境中安装它。如果你用这种安装方法时遇到问题,你可以随时
从项目主页上下载安装程序。
不幸的是,它不支持跨平台构建(交叉编译),因此如果你想要为某个特定平台构建独
立可执行文件,那么你需要在那个平台上执行构建。随着许多虚拟化工具的出现,这在今
天并不是一个大问题。如果你的计算机上没有安装某个特定的系统,你可是随时使用
Vagrant,它会为你提供所需要的操作系统作为虚拟机。
简单应用的用法很简单。假设我们的应用包含在名为 myscript.py 的脚本中。这是一个
简单的"Hello world!"应用。我们想要为 Windows 用户创建一个独立可执行文件,我们的源代码
位于文件系统的D://dev/app 目录下。利用下面这个简短的命令可以将我们的应用打包:
$ pyinstaller myscript.py
2121 INFO: PyInstaller: 3.1
2121 INFO: Python: 2.7.10
2121 INFO: Platform: Windows-7-6.1.7601-SP1
2121 INFO: wrote D:\dev\app\myscript.spec
2137 INFO: UPX is not available.
2138 INFO: Extending PYTHONPATH with paths
[‘D:\dev\app’, ‘D:\dev\app’]
2138 INFO: checking Analysis
2138 INFO: Building Analysis because out00-Analysis.toc is non
existent
2138 INFO: Initializing module dependency graph…
2154 INFO: Initializing module graph hooks…
2325 INFO: running Analysis out00-Analysis.toc
(…)
25884 INFO: Updating resource type 24 name 2 language 1033
即使是简单的应用,PyInstaller 的标准输出也相当长,所以为了简洁起见,上一个例子
只截取了一部分。如果在 Windows 上运行,生成的目录和文件结构如下所示:
$ tree /0066
│ myscript.py
│ myscript.spec

├───build
│ └───myscript
│ myscript.exe
│ myscript.exe.manifest
│ out00-Analysis.toc
│ out00-COLLECT.toc
│ out00-EXE.toc
│ out00-PKG.pkg
│ out00-PKG.toc
│ out00-PYZ.pyz
│ out00-PYZ.toc
│ warnmyscript.txt

└───dist
└───myscript
bz2.pyd
Microsoft.VC90.CRT.manifest
msvcm90.dll
msvcp90.dll
msvcr90.dll
myscript.exe
myscript.exe.manifest
python27.dll
select.pyd
unicodedata.pyd
_ _hashlib.pyd
dist/myscript 目录包含构建应用,现在可以分发给用户。注意,必须分发整个目
录。它包含运行应用所需要的所有附加文件(DLL、编译扩展库等)。利用 pyinstaller
命令的–onefile 开关可以得到更紧凑的发行版,如下所示:
$ pyinstaller --onefile myscript.py
(…)
$ tree /f
├───build
│ └───myscript
│ myscript.exe.manifest
│ out00-Analysis.toc
│ out00-EXE.toc
│ out00-PKG.pkg
│ out00-PKG.toc
│ out00-PYZ.pyz
│ out00-PYZ.toc
│ warnmyscript.txt

└───dist
myscript.exe
如果使用–onefile 选项进行构建,你唯一需要向用户分发的文件就是 dist 目录中
找到的单一可执行文件(这里是 myscript.exe)。对于小型应用来说,这可能是首选选项。
运行 pyinstaller 命令的一个副作用是创建了*.spec 文件。这是一个自动生成的
Python 模块,其中包含如何从源代码创建可执行文件的说明。例如,我们已经在下面的代
码中使用了这个:

-- mode: python --

block_cipher = None
a = Analysis([‘myscript.py’],
pathex=[‘D:\dev\app’],
binaries=None,
datas=None,
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name=‘myscript’,
debug=False,
strip=False,
upx=True,
console=True )
这个.spec 文件包含前面说过的所有 pyinstaller 参数。如果你对构建执行了大量
自定义,那么这一点是非常有用的,因为它可以用来替代保存配置的构建脚本。一旦创建
完成后,你可以用它而不是 Python 脚本作为 pyinstaller 命令的参数,如下所示:
$ pyinstaller.exe myscript.spec
注意,这是一个真正的 Python 模块,因此你可将其扩展,并利用你已经熟悉的语言对
构建过程执行更复杂的自定义。如果你面向许多不同的平台,那么自定义.spec 文件特别
有用。此外,不是所有的 pyinstaller 选项都可以通过命令行参数使用,只有在修
改.spec 文件时可以使用。
PyInstaller 是一个扩展工具,它对于绝大多数程序的用法都非常简单。无论如何,如果
你有兴趣用它作为分发应用的工具,那么推荐你深入阅读它的文档。

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值