WxPython跨平台开发框架之使用PyInstaller 进行打包处理

使用PyInstaller 打包Python项目是一个常见的需求,它可以将Python程序及其所有依赖项打包成一个独立的可执行文件或者安装文件,方便在没有安装Python环境的机器上运行。本随笔介绍WxPython跨平台开发框架中使用PyInstaller 进行打包处理,包括在WIndow平台下生成独立的exe文件,松散结构的exe文件和目录,以及在MacOS上生成安装包的处理过程。

1. 安装和使用 PyInstaller 进行程序打包处理

PyInstaller是目前最流行的Python打包工具之一。它可以将Python脚本打包成独立的可执行文件,支持Windows、Linux和macOS平台。

打包后的可执行文件可以在没有 Python 环境的机器上运行。PyInstaller 会自动分析程序的依赖关系,并将所有必要的库和资源打包到一个文件或者一个文件夹中。

cx_Freeze是另一个常用的Python打包工具,同样支持跨平台。

Py2exe是专门用于将Python脚本打包成Windows平台可执行文件的工具。

首先,确保您的Python环境已经安装。然后,通过pip安装PyInstaller。在VSCode或者其他编辑器的命令行(终端)中执行以下命令:

pip install pyinstaller

在项目目录下,使用PyInstaller命令来打包您的Python脚本。假设您的主程序文件名为main.py,则可以使用以下命令:

pyinstaller --onefile main.py

这里的--onefile选项指示PyInstaller生成一个单独的可执行文件,而不是一个包含多个文件的文件夹。PyInstaller还支持许多其他选项,如--icon来指定应用程序的图标,--windowed--noconsole来避免在Windows上打开命令行窗口等。

PyInstaller完成打包后,会在dist目录下生成可执行文件(或文件夹,如果您没有使用--onefile选项)。进入dist目录,您应该能看到一个名为main(或您指定的名称,如果使用了--name选项)的可执行文件。

如果一切正常,您的Python程序现在应该会在没有Python环境的情况下运行。

使用PyInstaller打包Python项目是一个简单而强大的方法,可以让您的程序更加便携和易于分发。通过遵循上述步骤,您可以轻松地将您的Python项目打包成一个可执行文件。

常用选项

PyInstaller 提供了很多命令行选项,用于定制打包过程。以下是一些常用的选项:

--onefile

生成单个可执行文件。默认情况下,PyInstaller 会生成一个文件夹,里面包含了可执行文件和所有相关的依赖项。如果你希望打包成一个独立的可执行文件(可能会更大),可以使用 --onefile 选项。

--noconsole

如果你正在创建一个 GUI 应用程序(如使用 wxPython 或 PyQt),并且不希望显示控制台窗口,可以使用 --noconsole 选项。此选项会隐藏控制台窗口,适用于 Windows 和 macOS。

--icon

为生成的可执行文件指定一个图标。图标文件可以是 .ico(Windows)或 .icns(macOS)格式。

--onedir

生成一个包含可执行文件和所有依赖项的文件夹,而不是单个文件。你可以将整个文件夹分发给其他用户。

build 文件夹被PyInstaller用来收集和准备捆绑的文件,它包含分析的结果和一些额外的日志。在大多数情况下,你可以忽略这个文件夹的内容,除非你想调试问题。

dist (代表 "分发")文件夹包含要分发的文件。这包括你的应用程序,捆绑成一个可执行文件,以及任何相关的库(例如WxPython、PyQt6 等)和二进制.so 文件。

 

2、使用.spec文件进行定制打包处理

打包过程中,PyInstaller 会生成一个 .spec 文件。这个文件包含了 PyInstaller 的配置信息,其中包含了构建过程的所有配置信息。你可以修改这个文件来定制打包过程。

如果我们执行下面代码

pyinstaller main.py

或者指定更多的参数的代码

pyinstaller --onefile --icon=your_icon.ico main.py

PyInstaller 都会生成一个 .spec 文件,然后可以编辑 main.spec 文件,例如:

# main.spec # -*- mode: python ; coding: utf-8 -*-  block_cipher = None  a = Analysis(['main.py'],              pathex=['/path/to/your/script'],  # 项目的路径              binaries=[],              datas=[('data/*.txt', 'data')],  # 资源文件              hiddenimports=['some_module'],  # 隐藏导入模块              hookspath=[],              runtime_hooks=[],              excludes=[],              win_no_prefer_redirects=False,              win_private_assemblies=False)  pyz = PYZ(a.pure)  exe = EXE(pyz,           a.scripts,           a.binaries,           a.zipfiles,           a.datas,           name='main',           debug=False,           strip=False,           upx=True,           console=False)  # 设置是否显示控制台

一般情况下,我们的.spec文件会比这个更多的内容,虽然原则上.spec文件支持跨平台的配置,不过我们在实际中往往根据不同的平台配置特定的.spec文件。

你可以手动修改 .spec 文件来添加资源文件、修改导入模块、定制输出路径等。

你可以通过编辑.spec 文件,在EXE、COLLECT和BUNDLE块下添加一个name= ,为PyInstaller提供一个更好的名字,以便为应用程序(和dist 文件夹)使用。

EXE下的名字是可执行文件的名字,BUNDLE下的名字是应用程序包的名字。

修改完成后,执行以下命令来重新打包:

解决常见问题

  • 缺少依赖库:如果打包后运行时出现缺少模块的错误,可以尝试将缺少的模块加入到 hiddenimports 中,或者通过 --hidden-import 选项指定:

  • 大文件:如果使用 --onefile 时打包后的文件太大,考虑使用 --onedir 或通过压缩文件等方法进行优化。
  • 处理资源文件:如果你的应用程序包含非 Python 代码的资源(如图像、配置文件、数据文件等),你需要通过 --add-data 选项指定资源文件的路径,或者在 .spec 文件中修改 datas 选项。
  • 动态链接库,如果你的应用程序依赖于特定的动态链接库(如 DLL 文件或 .so 文件),你需要将这些库包含到打包中。可以在 .spec 文件的 binaries 选项中指定:

  • 多平台支持:PyInstaller 支持 Windows、Linux 和 macOS 等多个平台,但需要在相应的平台上打包。例如,如果你要为 Windows 用户创建可执行文件,最好在 Windows 上运行 PyInstaller 来生成 Windows 的 .exe 文件。如果在 macOS 上打包,生成的文件只能在 macOS 上运行。

PyInstaller 有丰富的文档,提供了详细的使用说明和常见问题解答,你可以通过以下链接访问:

这些文档和资源能帮助你深入了解 PyInstaller 的使用方式,并解决在打包过程中可能遇到的问题。

 

3、WxPython跨平台开发框架中定制不同平台的 .spec文件

前面介绍了,我们推荐使用修改配置.spec文件的方式生成打包文件,并且可以通过定制不同平台的.spec文件,以便实现更好的处理,避免冲突。

对于不同平台的图标处理,我们可以使用代码来判断,.spec文件本身可以编写python的代码的。

import sys import os from pathlib import Path  if sys.platform == "win32":     icon = "app/images/app.ico" elif sys.platform == "darwin":     icon = "app/images/app.icns"

另外我们的业务窗体是动态根据路径解析的,因此在打包的时候,会漏掉的,为了解决这个问题,需要手动把视图部分的模块加载到hidden-import集合中,如下所示。

为了避免手工填写出错和麻烦,使用python函数递归处理目录的视图模块。

def collect_modules(directory):     modules = []     for root, dirs, files in os.walk(directory):         for file in files:             if file.endswith(".py") and file != "__init__.py":  # 排除 __init__.py 文件                 module_path = os.path.relpath(os.path.join(root, file), directory)                 module_name = module_path.replace(os.path.sep, ".").replace(".py", "")                 modules.append(module_name)     return modules   # 使用动态加载目录下的模块方式 hiddenimports = collect_modules("app/views") hiddenimports = [f"views.{module}" for module in hiddenimports]

这样在修改里面的变量即可。

# Analysis: PyInstaller Analysis object a = Analysis(     ["app/main.py"],     pathex=[],     binaries=[],     datas=[         ("app/images/splash.png", "images"),         ("app/.env", "."),         ("app/settings.ini", "."),     ],     hiddenimports=hiddenimports,     hookspath=[],     hooksconfig={},     runtime_hooks=[],     excludes=[],     noarchive=False,     optimize=0, )

1)WIndows平台的打包文件生成

然后指定EXE(用于Window的处理打包)

# PYZ: PyInstaller PYZ object pyz = PYZ(a.pure)  # EXE: PyInstaller EXE object exe = EXE(     pyz,     a.scripts,     a.binaries,     a.datas,     [],     name="wxpython_project",     debug=False,     bootloader_ignore_signals=False,     strip=False,     upx=True,     upx_exclude=[],     runtime_tmpdir=None,     console=False,  # True启用/False禁用命令行窗口     onefile=False,  # <-- False取消、True使用 onefile 模式     icon=icon,  # <-- 图标路径     disable_windowed_traceback=False,     argv_emulation=False,     target_arch=None,     codesign_identity=None,     entitlements_file=None, )

最后在dist目录上生成一个文件,如下所示。

WxPython跨平台开发框架之使用PyInstaller 进行打包处理

本文件用于Window平台下打包整个项目,生成一个独立的exe文件,包含了所有的依赖和资源文件,文件运行后会在临时目录中解压出来一个文件夹,程序退出后,该文件夹自动移除。

临时目录一般在C:UsersAdministratorAppDataLocalTemp。

 

如果我们想在Windows平台生成的dist目录中生成一个启动exe,和其他相关的Lib依赖库目录,那么我们可以适当调整下.spec文件,让它可以生成松散结构的文件目录包。

# PYZ: PyInstaller PYZ object pyz = PYZ(a.pure)  exe = EXE(     pyz,     a.scripts,     [],     exclude_binaries=True,     name="wxpython_project",     debug=False,     bootloader_ignore_signals=False,     strip=False,     upx=True,     console=False,  # True启用/False禁用命令行窗口     icon=icon,  # <-- 图标路径     disable_windowed_traceback=False,     argv_emulation=False,     target_arch=None,     codesign_identity=None,     entitlements_file=None, )  # COLLECT: PyInstaller COLLECT object coll = COLLECT(     exe,     a.binaries,     a.datas,     strip=False,     upx=True,     upx_exclude=[],     name="main", )

相当于之前在exe包中的a.binaries 和 a.datas从EXE 构造函数中移到了Collect的构造函数里面了。这样会生成下面的目录结构。

WxPython跨平台开发框架之使用PyInstaller 进行打包处理

其中_internal目录包含程序的相关依赖包和文件资源。

WxPython跨平台开发框架之使用PyInstaller 进行打包处理

如果我们需要使用第三方安装包制作工具(如SetupFactory ),那么整合这些文件即可实现安装程序的处理。

 

2)MacOs下的打包文件生成

 如果在MacOS或者Linux下的打包处理,会有所不同。

在MacOS中,我们需要使用 BUNDLE 创建 macOS 应用包
# 使用 BUNDLE 创建 macOS 应用包 app = BUNDLE(     coll,     name="wxpython_project.app",     icon=icon,     bundle_identifier="com.iqidi.wxpython_project",  # 推荐设置唯一的 bundle identifier     info_plist={         "NSPrincipalClass": "NSApplication",         "NSHighResolutionCapable": "True",     }, )

生成的 wxpython_project.app 应用程序捆绑包,实际上只是一个特殊的文件夹。

WxPython跨平台开发框架之使用PyInstaller 进行打包处理

虽然macOS将其显示为一个应用程序,但如果你试图分享它,你实际上将分享数百个单独的文件。为了正确分发应用程序,我们需要某种方式将其打包成一个单一的文件。

如果你以前安装过macOS应用程序,通常情况下你会得到一个磁盘镜像 .dmg ,打开后会显示应用程序包,以及一个指向应用程序文件夹的链接。要安装该应用程序,你只需将其拖到目标上。

为了创建我们的磁盘镜像,我们将使用create-dmg工具。这是一个命令行工具,它提供了一个简单的方法来自动建立磁盘镜像。如果你使用Homebrew,你可以用以下命令安装 create-dmg。

brew install create-dmg

create-dmg 是一个用于 macOS 的命令行工具,用于创建 .dmg (Disk Image) 文件,这些文件通常用于分发 macOS 应用程序。它简化了创建 .dmg 文件的过程,并允许你自定义磁盘映像的外观和行为。以下是 create-dmg 的一些主要功能和使用方法:

主要功能:

  1. 简单易用:通过命令行参数,快速创建 .dmg 文件。
  2. 自定义背景图片:可以为磁盘映像设置自定义背景图片。
  3. 应用程序放置位置:可以指定应用程序图标在磁盘映像中的位置。
  4. 图标大小和排列:自定义图标的大小和排列方式。
  5. 自动挂载和卸载:创建 .dmg 文件时自动挂载和卸载磁盘映像。

以下是一个简单的示例,用于创建一个 .dmg 文件:

create-dmg 'path/to/your/app' 'path/to/output/directory'

常用参数:

create-dmg 提供了多种参数来定制 .dmg 文件。以下是一些常用参数:

  • --overwrite:如果输出目录已经存在相同名称的 .dmg 文件,使用此参数将其覆盖。
  • --background:指定 .dmg 文件的背景图片。
  • --icon:设置应用程序图标的位置,格式为 name:x,y,例如:--icon "YourAppName:150,150".
  • --icon-size:设置图标的大小,默认值为 80。
  • --window-size:设置 .dmg 窗口的大小,格式为 width,height,例如:--window-size 600,400.
  • --title:设置 .dmg 窗口的标题。

以下是一个更复杂的示例,展示了如何使用多个参数来自定义 .dmg 文件:

create-dmg 'path/to/your/app' 'path/to/output/directory'    --overwrite    --background 'path/to/background.png'    --icon 'YourAppName:150,150'    --icon-size 100    --window-size 800,600    --title 'YourAppName Installer'

 

发表评论

相关文章