使用PyInstaller打包Python应用程序

本文最后更新于:2020年9月9日 晚上

一、简述

PyInstaller 官网:https://www.pyinstaller.org

PyInstaller 可以将 Python 程序及其依赖的包打包为一个可执行程序方便安装使用。

PyInstaller 可以将 Python 程序打包为一个独立的可执行程序或者一个包含可执行程序的文件夹,区别在于单文件的程序运行较慢,而文件夹的程序运行较快。

如果要打包为一个包含可执行程序的文件夹,需要注意将附加的文件添加进来,PyInstaller 指挥根据 Python 脚本搜索依赖的包,但不会自动包含参数配置文件之类的文件。同时如果需要将程序发布出来供他人使用,则需要将打包后的文件夹制作成压缩包用于分发,或者额外制作安装程序(例如可以使用 NSIS 制作安装包)。

二、安装

建议:使用 virtualenv 将依赖的包安装到虚拟环境中。

使用 pip 安装和升级 PyInstaller。

# 安装
pip install pyinstaller

# 升级
pip install --upgrade pyinstaller

可选安装最新开发版。

pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz

三、使用

(1)命令行方式

1. 基本命令

注意:推荐使用另外两种方式,但它们的使用方法也都基于命令行选项。

基本语法结构如下:

pyinstaller [options] script [script …] | specfile

In the most simple case, set the current directory to the location of your program myscript.py and execute:

最简单的情况是,在 Python 程序 myscript.py 目录下直接执行:

pyinstaller myscript.py

PyInstaller 会分析 myscript.py 并:

  • 在当前目录下创建 myscript.spec 脚本;
  • 创建 builddist 文件夹;
  • build 文件夹中创建一些日志或工作文件;
  • dist 文件夹中创建 myscript 文件夹,内含可执行的应用程序。

使用 .spec 的脚本文件可以避免每次都要输入很长的参数,后面会讲到。

2. 参数设置

仅列举了较常用的一些选项,更多信息请查阅官方文档:https://pyinstaller.readthedocs.io/en/latest/usage.html#options

当使用较多选项时命令会很长,可以将命令写到脚本文件中备用。

1. 常规设置

  • –distpath DIR

    存放生成的程序的路径。 (default: ./dist)

  • –workpath WORKPATH

    存放一些 PyInstaller 工作生成的文件,.log, .pyzetc 。 (default: ./build)

  • -y, –noconfirm

    如果程序文件夹存在的话直接替换不需要确认。 (default: SPECPATH/dist/SPECNAME)

  • –upx-dir UPX_DIR

    UPX 程序的路径。 (default: search the execution path)

    简单说 UPX (官方网站)的作用就是压缩。UPX 需要额外下载安装,下载后解压缩即可。

    要使用 UPX 的话可以直接将 UPX 程序(upx.exe)放到虚拟环境的 ./venv/Scripts 目录下即可,无需设置该选项。

  • –clean

    Build 之前先清理 PyInstaller 缓存和临时文件。

2. 生成什么

  • -D, –onedir

    默认选项,创建一个包含可执行程序的文件夹,运行速度较快。

  • -F, –onefile

    创建一个单文件的可执行程序,运行速度较慢。

  • –specpath DIR

    指定存放 .spec 脚本的路径,默认为当前文件夹。

  • -n NAME, –name NAME

    指定 spec 文件和要生成的程序的文件名。 (default: first script’s basename)

3. 打包那些东西以及去哪里找

  • –add-data <SRC;DEST or SRC:DEST>

    附加的非二进制文件或文件夹,例如保存参数设置的 config.json 文件。分隔符在 Windows 系统中一般为 ; ,在大多 UNIX 系统中一般为 : 。该参数可多次重复使用以添加多个附加文件。

  • –add-binary <SRC;DEST or SRC:DEST>

    附加的二进制文件。使用方式同 --add-data 选项。

  • -p DIR, –paths DIR

    搜索依赖的包的路径,可以使用 : 添加多条路径,或者多次使用该选项。

  • –hidden-import MODULENAME, –hiddenimport MODULENAME

    列举在 Python 脚本中不可见的导入,不能搜索到的包。该选项可多次使用。

4. 怎么生成

  • -d <all,imports,bootloader,noarchive>, –debug <all,imports,bootloader,noarchive>

    用于调试,具体说明请查阅官方文档

  • –noupx

    即使 UPX 可用也不使用,如果使用 UPX 后程序无法正常运行可以使用该选项。

  • –upx-exclude FILE

    指定不需要压缩的二进制文件,防止 UPX 在压缩过程中破坏了一些二进制文件。

5. Windows 和 Mac OS 特定选项

  • -c, –console, –nowindowed

    打开一个命令行窗口用于标准 I/O (default)。在 Windows 上,如果第一个脚本是 .pyw 文件,则此选项无效。

  • -w, –windowed, –noconsole

    不打开命令行窗口用于标准 I/O 。

  • -i <FILE.ico or FILE.exe,ID or FILE.icns>, –icon <FILE.ico or FILE.exe,ID or FILE.icns>

    设置程序的图标。FILE.ico: apply that icon to a Windows executable. FILE.exe,ID, extract the icon with ID from an exe. FILE.icns: apply the icon to the .app bundle on Mac OS X.

6. Windows 特定选项

  • –uac-admin

    程序运行时请求提升权限。

(2)使用 spec 文件

实际上不管使用哪种方式都会生成一个 spec 文件,里面包含了大多数设置的参数。

可以使用以下命令创建 spec 文件:

pyi-makespec [options] name.py [other scripts ...]

当创建并根据需要修改了 spec 文件后,就可以简单的通过以下命令运行:

pyinstaller [options] name.spec

spec 文件结构如下:

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['../main.py'],  # 指定主程序脚本
             pathex=['D:/path/to/project'],  # 设置项目路径
             binaries=[],  # 指定要添加的二进制文件
             datas=[('../settings.json', '.'),
                    ('../version.txt', '.'),
                    ('../img', 'img'),
                    ('../font', 'font')],  # 指定要添加的非二进制文件或文件夹
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='Radar0.0.12',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=False,  # 是否使用UPX压缩
          console=False , 
          icon='../img/logo64.ico')  # 程序图标
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=False,
               upx_exclude=['vcruntime140.dll'],
               name='Radar0.0.12')

(3)在 Python 中运行

1. 使用 PyInstaller 内置的 run() 函数

传入参数列表即可

import PyInstaller.__main__


parameters = [
    '../main.py',
    f'--name={program_name}',
    '--distpath=./dist',
    '--workpath=./build',
    '--clean',
    '-D',
    '-w',
    '-i=../img/logo64.ico',
    '--add-data=../settings.json;.',
    '--add-data=../version.txt;.',
    '--add-data=../img;img',
    '--add-data=../font;font',
    '--noupx',
]

PyInstaller.__main__.run(parameters)  # RUN

2. 在 Python 中执行命令

等同于在终端中执行命令,但可以通过 Python 执行更多的定制化的操作。

import subprocess


p = subprocess.Popen('pyinstaller radar.spec --clean', shell=True)
p.communicate()

四、 其它说明

嗯,好像没啥好说明的了,遇到问题搜索一下还是比较容易解决的。

UPX 压缩极有可能会有问题,用不了就干脆不用了,也没能压缩太多,我测试的程序不压缩 80 MB,压缩后 62 MB,个人认为不压缩也是可以接受的。

另外推荐使用 NSIS 制作安装程序ฅʕ•̫͡•ʔฅ


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!