Pyinstaller 入门简介

发布于 18 小时前  32 次阅读


  本篇博客将简要介绍如何使用pyinstaller构建、打包一个python程序。这里我们将以C风格的方式(.spec配置文件 + build脚本)来打包我们的目标源码。因此我们需要准备如下的内容:

  1. main.py,目标源码;
  2. build_config.spec,构建配置;
  3. build.py,构建脚本。

一、main.py

  这里我们将实现一个最基本的python程序,我们期望通过如下的方式来调用它:

(base)PS C:\Users\x\Downloads\src> python main.py --print "Hello"
[INFO] 接收到的参数内容:  Hello

  其源代码如下:

# main.py

# 标准库
import argparse
import sys
# 第三方库
from colorama import init, Fore, Style

# 初始化 colorama
init()

def main():
    # 1. 创建 ArgumentParser 对象
    parser = argparse.ArgumentParser(description="一个用于演示 PyInstaller 打包的示例程序")

    # 2. 添加参数 --print
    parser.add_argument('--print', type=str, help='需要打印的字符串内容')

    # 3. 解析参数
    args = parser.parse_args()

    # 4. 业务逻辑
    if args.print:
        # 使用第三方库 colorama 输出绿色文字
        print(f"{Fore.GREEN}[INFO] 接收到的参数内容: {Style.RESET_ALL} {args.print}")
    else:
        print(f"{Fore.RED}[ERROR] 未提供 --print 参数。{Style.RESET_ALL}")
        print(f"用法示例: {sys.argv[0]} --print \"Hello World\"")

if __name__ == "__main__":
    main()

这里我们编写了一个最基本的IO程序,同时加入了第三方库colorama,让程序更贴近实际使用的情况。

二、build_config.spec

  在验证了上述代码的正确性后,我们尝试使用pyinstaller对其进行打包。为了更好的控制编译过程,我们这里不直接采用pyinstaller xxxxxx的方式来编译,而是像makefile一样编写一个专门的文件。其源码如下:

# demo_app.spec
# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

a = Analysis(
    ['main.py'],             # 源代码列表
    pathex=[],               # 额外的搜索路径
    binaries=[],             # 需要包含的二进制文件 (如 .dll, .so)
    datas=[],                # 非代码资源文件 (如图片, 配置文件)
    hiddenimports=[],        # PyInstaller 无法自动检测到的隐式导入库
    hookspath=[],
    hooksconfig={},
    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,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='demo_app',          # 输出的可执行文件名
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,                 # 是否使用 UPX 压缩
    upx_exclude=[],
    runtime_tmpdir=None,
    console=True,             # True=显示控制台(命令行程序), False=隐藏(GUI程序)
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

三、build.py

  在编写完了上述配置文件后,我们可以用类似make xxxx.conf的方式来调用它;同样的,我们这里依然采用编写一个脚本(bash、powershell均可)来控制构建的流程,为了方便,我们这里依然选择使用python来作为构建脚本。其源码如下:

# build.py
import PyInstaller.__main__
import os
import shutil

def build():
    print("使用 Spec 文件开始构建...")

    # 1. clean原有构建文件
    if os.path.exists('dist'):
        shutil.rmtree('dist')
    if os.path.exists('build'):
        shutil.rmtree('build')

    # 2. 选择配置文件 build_config.spec
    params = [
        'build_config.spec',
        # 构建前清理文件
        '--clean'
    ]

    # 3. (Make) 调用pyinstaller执行构建
    PyInstaller.__main__.run(params)

    print("构建完成!")

if __name__ == "__main__":
    build()

四、验证

  在编写完成了上述代码之后,我们的工程目录如下:

.
├── build_config.spec
├── build.py
└── main.py

  我们首先进行main.py的功能验证:

(base)PS C:\Users\x\Downloads\src> python main.py --print "功能验证"
[INFO] 接收到的参数内容:  功能验证

确认没有问题之后,通过build.py进行编译:

(base)PS C:\Users\x\Downloads\src> python build.py
使用 Spec 文件开始构建...
579 INFO: PyInstaller: 6.11.1, contrib hooks: 2025.0
580 INFO: Python: 3.12.4 (conda)
602 INFO: Platform: Windows-11-10.0.26100-SP0
602 INFO: Python environment: C:\Users\x\miniconda3
609 INFO: Removing temporary files and cleaning cache in C:\Users\x\AppData\Local\pyinstaller
611 INFO: Module search paths (PYTHONPATH):
['C:\\Users\\x\\Downloads\\src',
 'C:\\Users\\x\\miniconda3\\python312.zip',
 'C:\\Users\\x\\miniconda3\\DLLs',
 'C:\\Users\\x\\miniconda3\\Lib',
 'C:\\Users\\x\\miniconda3',
 'C:\\Users\\x\\miniconda3\\Lib\\site-packages',
 'C:\\Users\\x\\miniconda3\\Lib\\site-packages\\win32',
 'C:\\Users\\x\\miniconda3\\Lib\\site-packages\\win32\\lib',
 'C:\\Users\\x\\miniconda3\\Lib\\site-packages\\Pythonwin',
 'C:\\Users\\x\\Downloads\\src']
1367 INFO: checking Analysis
1367 INFO: Building Analysis because Analysis-00.toc is non existent
1367 INFO: Running Analysis Analysis-00.toc
1367 INFO: Target bytecode optimization level: 0
1369 INFO: Initializing module dependency graph...
1370 INFO: Initializing module graph hook caches...
1398 INFO: Analyzing base_library.zip ...
3690 INFO: Processing standard module hook 'hook-encodings.py' from 'C:\\Users\\x\\miniconda3\\Lib\\site-packages\\PyInstaller\\hooks'
5436 INFO: Processing standard module hook 'hook-pickle.py' from 'C:\\Users\\x\\miniconda3\\Lib\\site-packages\\PyInstaller\\hooks'
6307 INFO: Processing standard module hook 'hook-heapq.py' from 'C:\\Users\\x\\miniconda3\\Lib\\site-packages\\PyInstaller\\hooks'
6755 INFO: Caching module dependency graph...
6865 INFO: Looking for Python shared library...
6872 INFO: Using Python shared library: C:\Users\x\miniconda3\python312.dll
6872 INFO: Analyzing C:\Users\x\Downloads\src\main.py
6934 INFO: Processing module hooks (post-graph stage)...
6938 INFO: Performing binary vs. data reclassification (2 entries)
6941 INFO: Looking for ctypes DLLs
6947 INFO: Analyzing run-time hooks ...
6949 INFO: Including run-time hook 'pyi_rth_inspect.py' from 'C:\\Users\\x\\miniconda3\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
6953 INFO: Looking for dynamic libraries
7150 INFO: Extra DLL search directories (AddDllDirectory): []
7151 INFO: Extra DLL search directories (PATH): []
7702 INFO: Warnings written to C:\Users\x\Downloads\src\build\build_config\warn-build_config.txt
7725 INFO: Graph cross-reference written to C:\Users\x\Downloads\src\build\build_config\xref-build_config.html
7762 INFO: checking PYZ
7762 INFO: Building PYZ because PYZ-00.toc is non existent
7762 INFO: Building PYZ (ZlibArchive) C:\Users\x\Downloads\src\build\build_config\PYZ-00.pyz
8015 INFO: Building PYZ (ZlibArchive) C:\Users\x\Downloads\src\build\build_config\PYZ-00.pyz completed successfully.
8029 INFO: checking PKG
8029 INFO: Building PKG because PKG-00.toc is non existent
8029 INFO: Building PKG (CArchive) demo_app.pkg
9912 INFO: Building PKG (CArchive) demo_app.pkg completed successfully.
9914 INFO: Bootloader C:\Users\x\miniconda3\Lib\site-packages\PyInstaller\bootloader\Windows-64bit-intel\run.exe
9914 INFO: checking EXE
9915 INFO: Building EXE because EXE-00.toc is non existent
9915 INFO: Building EXE from EXE-00.toc
9915 INFO: Copying bootloader EXE to C:\Users\x\Downloads\src\dist\demo_app.exe
9925 INFO: Copying icon to EXE
9933 INFO: Copying 0 resources to EXE
9934 INFO: Embedding manifest in EXE
9941 INFO: Appending PKG archive to EXE
9957 INFO: Fixing EXE headers
10044 INFO: Building EXE from EXE-00.toc completed successfully.
构建完成!
(base)PS C:\Users\x\Downloads\src>

我们可以看到,已经成功编译了main.py,输出的结果为dist/demo_app.exe,我们尝试调用它:

(base)PS C:\Users\x\Downloads\src> .\dist\demo_app.exe --print "验证构建产物"
[INFO] 接收到的参数内容:  验证构建产物

至此我们这里完成了通过pyinstaller进行python程序打包的这一目的。