使用PyInstaller打包可执行文件

0x00 前言

之前都是使用py2exe将Python程序打包成可执行文件,但是最近需要打包成Macos上的可执行程序。于是,选择了py2app,但是使用下来发现坑比较多,最终还是放弃了。

于是,将目光转向了PyInstaller,它可以同时支持Windows和Macos,并且使用方法差异也很小。

PyInstaller与py2exe的主要差异(Windows):

  • PyInstaller打包出来的是一个正常的exe;py2exe打包出来的既是exe,也是zip文件,可以进行解压

  • PyInstaller打包出来的程序在运行后会创建一个临时目录,把dll等文件解压到临时目录中;py2exe使用了内存加载dll的技术,可以在不解压dll的情况下直接加载,看上去更优雅一些

0x01 环境准备

测试过程使用了virtualenv创建的虚拟环境,可以保证测试过程不会影响到系统的Python环境。

$ virtualenv .env
$ .env\Scripts\activate.bat(Windows)
$ source .env/bin/activate (类Unix)
$ pip install PyInstaller
$ pyinstaller
usage: pyinstaller [-h] [-v] [-D] [-F] [--specpath DIR] [-n NAME]
                   [--add-data <SRC;DEST or SRC:DEST>]
                   [--add-binary <SRC;DEST or SRC:DEST>] [-p DIR]
                   [--hidden-import MODULENAME]
                   [--additional-hooks-dir HOOKSPATH]
                   [--runtime-hook RUNTIME_HOOKS] [--exclude-module EXCLUDES]
                   [--key KEY] [-d [{all,imports,bootloader,noarchive}]] [-s]
                   [--noupx] [-c] [-w]
                   [-i <FILE.ico or FILE.exe,ID or FILE.icns>]
                   [--version-file FILE] [-m <FILE or XML>] [-r RESOURCE]
                   [--uac-admin] [--uac-uiaccess] [--win-private-assemblies]
                   [--win-no-prefer-redirects]
                   [--osx-bundle-identifier BUNDLE_IDENTIFIER]
                   [--runtime-tmpdir PATH] [--bootloader-ignore-signals]
                   [--distpath DIR] [--workpath WORKPATH] [-y]
                   [--upx-dir UPX_DIR] [-a] [--clean] [--log-level LEVEL]
                   scriptname [scriptname ...]
pyinstaller: error: too few arguments

0x02 PyInstaller参数说明

官方文档地址为:https://pyinstaller.readthedocs.io/en/stable/usage.html

常用参数含义如下:

+--------------+----------------------------------------------+
|-h, --help    | 帮助信息                                      |
+-------------------------------------------------------------+
|-v, --version | 版本信息                                      |
+-------------------------------------------------------------+
|--distpath DIR| 打包文件的保存目录(默认:dist)                |
+-------------------------------------------------------------+
|--workpath WORKPATH| 临时文件的保存目录(默认:build)          |
+-------------------------------------------------------------+
|-y, --noconfirm    | 替换文件时无需确认                        |
+-------------------------------------------------------------+
|--upx-dir UPX_DIR  | UPX程序所在目录                          |
+-------------------------------------------------------------+
|-a, --ascii        | 不包含unicode编码支持                    |
+-------------------------------------------------------------+
|--clean            | 编译前先清理缓存和临时文件                |
+-------------------------------------------------------------+
|--log-level LEVEL  | 编译时的日志等级:TRACE, DEBUG, INFO,     |
|                   | WARN, ERROR, CRITICAL,默认是:INFO      |
+-------------------------------------------------------------+
|-D, --onedir       | 生成的所有文件保存到一个目录(默认)       |
+-------------------------------------------------------------+
|-F, --onefile      | 只生成一个文件(exe)                     |
+-------------------------------------------------------------+
|–specpath          | .spec文件保存目录(默认是当前目录)        |
+-------------------------------------------------------------+
|-n                 | 生成的文件名(默认是指定的Python脚本名称) |
+-------------------------------------------------------------+
|-i                 | 指定程序图标 Windows: *.ico Macos: *.icns|
+-------------------------------------------------------------+
|-w                 | 不显示命令行窗口                         |
+-------------------------------------------------------------+

一般可以使用以下命令行创建一个GUI的可执行文件:

pyinstaller -F -w main.py -n demo

执行后,可以在dist目录下创建demo.exe(Windows)或demo.app(Macos)

0x03 指定程序图标

一般可执行程序都会包含个性化的图标,但是Windows和Macos使用了不同的图标格式。Windows上一般是常见的*.ico格式;而Macos上则是*.icns

ico图标的制作可以使用一些在线网站或小工具

制作icns图标可以使用如下方法(Macos):

  1. 准备好一张长宽相等的png图片(最好背景透明),重命名为pic.png

  2. 创建目录tmp.iconset

  3. 执行以下命令,生成图标集

sips -z 16 16     pic.png --out tmp.iconset/icon_16x16.png
sips -z 32 32     pic.png --out tmp.iconset/icon_16x16@2x.png
sips -z 32 32     pic.png --out tmp.iconset/icon_32x32.png
sips -z 64 64     pic.png --out tmp.iconset/icon_32x32@2x.png
sips -z 128 128   pic.png --out tmp.iconset/icon_128x128.png
sips -z 256 256   pic.png --out tmp.iconset/icon_128x128@2x.png
sips -z 256 256   pic.png --out tmp.iconset/icon_256x256.png
sips -z 512 512   pic.png --out tmp.iconset/icon_256x256@2x.png
sips -z 512 512   pic.png --out tmp.iconset/icon_512x512.png
sips -z 1024 1024 pic.png --out tmp.iconset/icon_512x512@2x.png
  1. 执行以下命令创建icns图标文件
$ iconutil -c icns tmp.iconset -o pic.icns

指定程序图标只要在命令行后面增加参数:

-i pic.icon/pic.icns

0x04 添加数据文件

程序中有时需要用到一些数据文件,可以使用--add-data=src;dst(Windows)或--add-data=src:ds(类Unix)参数将src路径对应的文件(夹)拷贝到dst指向的路径,程序中可以使用dst路径进行访问。

由于PyInstaller打包出来的程序在运行时会解压数据文件到临时目录中,因此程序中可以直接访问这些数据文件;而py2exe则需要手动将数据文件从程序体中解压出来使用。

0x05 添加版本信息(Windows)

PyInstaller允许在Windows上给程序添加版本信息,使用--version-file version_file.txt参数进行添加。

version_file.txt文件的制作方法如下:

  1. 根据已有的exe文件生成版本文件模版
$ pyi-grab_version demo.exe version_file.txt
  1. 修改version_file.txt中的文件名、厂商、版本等信息,并保存

为了动态修改版本信息,也可以使用脚本动态生成版本文件

0x06 打包成app( Macos)

在Macos上使用PyInstaller打包出来的是一个目录,可以直接压缩成zip文件给其他人使用,但更多的是打包成dmg格式。这可以使用App2Dmg这款应用完成。

选择应用目录和要保存的目录后,就会生成.dmg文件了

分享