Python程序打包 PyInstaller详解

JaosnY 2024-09-04 11:05:01 阅读 91

Python程序打包 PyInstaller详解

PyInstaller 是一个将 Python 程序及其依赖项打包成独立可执行文件的工具,适用于 Windows、macOS 和 Linux。它通过分析你的代码来确定所需的模块,并将其包含在一个可执行文件中,这样你就可以在没有 Python 解释器的系统上运行你的程序。

下面是使用 PyInstaller 将一个简单的 Python 脚本打包成可执行文件的步骤:

第一步:安装 PyInstaller

首先,你需要确保 PyInstaller 已经安装在你的系统上。如果没有安装,可以通过 pip 来安装:

<code>pip install pyinstaller

或者如果你使用的是 Python3,可能需要使用

pip3 命令:

pip3 install pyinstaller

第二步:准备你的 Python 脚本

        假设你有一个名为 my_script.py 的 Python 脚本,位于你的工作目录中。这个脚本可以是任何有效的 Python 程序。

第三步:创建.spec 文件(可选)

PyInstaller 可以从命令行直接使用,但是为了更高级的配置,你可能需要创建一个 .spec 文件。这个文件允许你定制 PyInstaller 的行为,例如指定要包含的额外文件或模块。

创建一个与你的脚本同名的 .spec 文件,例如 my_script.spec,并编辑它以包含以下内容:

# my_script.spec

block_cipher = None

a = Analysis(['my_script.py'],

pathex=['/path/to/your/script'], #默认Bash当前目录

binaries=[],

datas=[],

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,

a.binaries,

a.zipfiles,

a.datas,

name='my_script',code>

debug=False,

bootloader_ignore_signals=False,

strip=False,

upx=True,

console=True )

第四步:使用 PyInstaller 命令行工具

最简单的方法是直接在命令行中使用 PyInstaller。假设你的脚本位于当前目录下,你可以使用以下命令来生成可执行文件

pyinstaller --onefile my_script.py

这会将你的脚本打包成一个单独的可执行文件。--onefile 参数告诉 PyInstaller 创建一个单一的可执行文件,而不是一个包含多个文件的文件夹。

第五步:检查输出

运行完 PyInstaller 后,你会在 dist 目录下找到你的可执行文件。对于 Windows,它将是 my_script.exe;对于 macOS,它将是一个应用程序包;对于 Linux,它将是一个可执行文件。

第六步:测试你的可执行文件

在分发之前,你应该在不同的系统上测试你的可执行文件,以确保它能够正常运行。

第七步:解决依赖问题

如果在测试时遇到任何问题,可能是由于缺少某些依赖模块。你可能需要在 .spec 文件中添加 hiddenimports 或者在命令行中使用 --hidden-import 参数来显式包含这些模块。

以上就是使用 PyInstaller 打包 Python 脚本的基本流程。根据你的具体需求,可能还需要对 .spec 文件进行更详细的配置。

注意事项

1.PyInstaller 打包需确保第三库及用到的资源导入

a.第三库导入

当你在 Python 脚本中使用了多个第三方库并且想要使用 PyInstaller 打包时,你可能需要在 .spec 文件中明确列出所有这些库中的隐藏导入,

以确保它们都被正确地包含在最终的可执行文件中。

下面是一个针对你提供的模块列表的示例 .spec 文件。这个 .spec 文件将会包括你提到的所有模块和库:

# my_script.spec #和需要打包的py同名

# The block_cipher variable is not used in this case.

block_cipher = None

# Define the Analysis object with your script and any hidden imports.

a = Analysis(['my_script.py'], #需要打包的文件

pathex=['/path/to/your/script'], #需要打包的文件路径

binaries=[],

datas=[], #需要用到的资料,如:图像、音频等非py的文件,都需要列出来

hiddenimports=['tkinter', 'tkinter.filedialog', 'psd_tools', 'PIL.Image',

'psd_tools.PSDImage', 'PIL.ImageTk', 'sys', 'os', 're',

'tkinter.ttk', 'time', 'pickle', 'tkinter.messagebox'],

hookspath=[],

runtime_hooks=[],

excludes=[],

win_no_prefer_redirects=False,

win_private_assemblies=False,

cipher=block_cipher,

noarchive=False)

# Define the PYZ object for the compressed module data.

pyz = PYZ(a.pure, a.zipped_data,

cipher=block_cipher)

# Define the EXE object to create the final executable.

exe = EXE(pyz,

a.scripts,

a.binaries,

a.zipfiles,

a.datas,

name='my_script',code>

debug=False,

bootloader_ignore_signals=False,

strip=False,

upx=True,

console=True )

但是请注意,hiddenimports 列表中的模块名应该是那些在标准分析过程中不会被自动检测到的模块名。在大多数情况下,像 tkinter, PIL 这些常见的库会被自动检测到,除非它们使用了一些特殊的导入方式,比如延迟导入或动态导入。

对于 tkinter 和 PIL 这样的库,通常不需要在 hiddenimports 中列出它们的标准模块,但它们的子模块可能需要。例如,PIL.ImageTk 和 tkinter.filedialog 需要被明确列出。

另外,你也可以使用 PyInstaller 的 --hidden-import 参数从命令行来指定这些隐藏导入,例如:

pyinstaller --onefile --hidden-import=PIL.ImageTk --hidden-import=tkinter.filedialog my_script.py

这样可以避免修改 .spec 文件。但是,.spec 文件提供了更多的灵活性和控制,特别是在处理更复杂的项目时。

在实际应用中,你可能需要根据实际情况调整 hiddenimports 列表。如果在运行打包后的程序时遇到缺失模块的错误,

那么就需要检查并添加相应的模块到 hiddenimports 中。

如果你的主脚本依赖于其他的 .py 文件,比如 Jswindow.py 和 JSNetwork.py,你需要确保 PyInstaller 也能识别并包含这些文件。通常,只要这些文件在你的主脚本的搜索路径中(通常是同一目录下),PyInstaller 应该能自动检测到它们。

但是,为了确保万无一失,你可以在 .spec 文件中显式地指出这些文件。你也可以通过添加 datas 或者 binaries 来包括任何非 Python 的数据文件或二进制文件,如果有的话。

下面是一个修改后的 .spec 文件示例,其中包括了 Jswindow.py 和 JSNetwork.py 文件:

# my_script.spec

# The block_cipher variable is not used in this case.

block_cipher = None

# Define the Analysis object with your script and any hidden imports.

a = Analysis(['my_script.py'],

pathex=['/path/to/your/script'],

binaries=[],

datas=[('Jswindow.py', '.'), ('JSNetwork.py', '.')],

hiddenimports=['tkinter', 'tkinter.filedialog', 'psd_tools', 'PIL.Image',

'psd_tools.PSDImage', 'PIL.ImageTk', 'sys', 'os', 're',

'tkinter.ttk', 'time', 'pickle', 'tkinter.messagebox'],

hookspath=[],

runtime_hooks=[],

excludes=[],

win_no_prefer_redirects=False,

win_private_assemblies=False,

cipher=block_cipher,

noarchive=False)

# Define the PYZ object for the compressed module data.

pyz = PYZ(a.pure, a.zipped_data,

cipher=block_cipher)

# Define the EXE object to create the final executable.

exe = EXE(pyz,

a.scripts,

a.binaries + a.collect_data,

a.zipfiles,

a.datas,

name='my_script',code>

debug=False,

bootloader_ignore_signals=False,

strip=False,

upx=True,

console=True )

在 datas 列表中,('Jswindow.py', '.') 和 ('JSNetwork.py', '.') 表示将 Jswindow.py 和 JSNetwork.py 文件包含在最终的输出中,它们会被放置在与可执行文件相同的目录下。

然而,对于 .py 文件,通常不需要将它们添加到 datas 中,因为它们会被当作 Python 模块处理。datas 主要用于包含数据文件,如图像、配置文件等。如果你的 Jswindow.py 和 JSNetwork.py 是作为模块被导入的,那么只需要确保它们在正确的路径下即可。

如果你的 Jswindow.py 和 JSNetwork.py 文件中有额外的依赖或需要包含的资源,你可能还需要在 hiddenimports 或 datas 中添加相应的条目。

另外,你也可以通过命令行参数来包含额外的文件或模块,例如:

pyinstaller --onefile --additional-hooks-dir=path/to/hooks my_script.py

b.应用资源文件导入

默认情况下 PyInstaller 不会收集所有的非Python资源文件,包括像 .ico 这样的图标文件。

为了确保图标文件也被包含在打包的可执行文件中,你需要告诉 PyInstaller 明确地包含这些文件。你可以在 .spec 文件中添加 datas 参数来实现这一点。datas 参数允许你指定额外的数据文件及其目标位置。

下面是如何在 .spec 文件中使用 datas 参数的例子:

a = Analysis(['your_script.py'],

pathex=['/path/to/your/script'],

binaries=[],

datas=[('favicon.ico', '.')], # 这里添加你的图标文件

...

)

pyz = PYZ(a.pure, a.zipped_data,

cipher=block_cipher)

exe = EXE(pyz,

a.scripts,

a.binaries,

a.zipfiles,

a.datas,

name='YourAppName',code>

debug=False,

strip=False,

upx=True,

console=False, #不显示控制台窗口

icon='favicon.ico', # 同时在这里指定图标文件code>

...

)

在这个例子中,datas=[('favicon.ico', '.')] 表示 favicon.ico 文件应该被包含在最终的可执行文件中,并且它会被放置在可执行文件的根目录下。然后在 EXE 对象中再次指定图标文件,这样它就会被正确地嵌入到可执行文件中。

另外,如果你在使用 PyInstaller 的命令行版本,你可以使用 --additional-hooks-dir 参数指向一个包含自定义钩子脚本的目录,在这个目录中的钩子脚本可以用来告诉 PyInstaller 如何处理特定类型的文件。但是,对于简单的图标文件,使用 .spec 文件中的 datas 参数通常就足够了。

2.执行文件在运行时关闭控制台窗口

在使用 PyInstaller 打包 Python 脚本时,如果你不希望生成的可执行文件在运行时显示命令行窗口(控制台窗口),特别是在 Windows 平台上,你可以通过设置 console 参数为 False 来实现。

在你的 .spec 文件中,找到 exe 的定义部分,将 console 设置为 False。这将告诉 PyInstaller 生成一个没有控制台窗口的 GUI 应用程序。以下是一个示例:

# my_script.spec

# ...

# Define the EXE object to create the final executable.

exe = EXE(pyz,

a.scripts,

a.binaries + a.collect_data,

a.zipfiles,

a.datas,

name='my_script',code>

debug=False,

bootloader_ignore_signals=False,

strip=False,

upx=True,

console=False ) # Set console to False for no console window on Windows

3.图标:指定打包后的exe图标

要在使用 PyInstaller 打包的程序中添加自定义图标,你需要遵循以下几个步骤:

1.准备图标文件

首先,确保你有一个 .ico 图标文件。这个图标将会被嵌入到你的可执行文件中,当你在文件资源管理器中查看该文件时,它将显示你选择的图标。

2.修改 .spec 文件

在你的 .spec 文件中,你需要添加一个 icon 属性来引用你的图标文件。假设你的图标文件叫做 my_icon.ico,并且它位于与你的 .spec 文件相同的目录下,你可以在 EXE 对象中添加 icon 参数,如下所示:

exe = EXE( ..., icon='my_icon.ico', ... )code>

3.使用命令行参数:

.spec 文件,你可以在运行 PyInstaller 命令时添加 --icon 参数,后面跟上你的图标文件路径。例如:

pyinstaller --onefile --windowed --icon=my_icon.ico my_script.py

这个命令会创建一个单文件的可执行程序,并且在其中嵌入了你指定的图标

4.确保图标文件的兼容性

请确保你的图标文件是 Windows 兼容的格式,通常这意味着它应该是一个 .ico 文件,且包含不同尺寸的图标以便在不同的设备和 DPI 设置下显示良好。

5.测试

在打包完成后,运行生成的可执行文件并检查是否正确显示了你选择的图标。

请注意,如果你在打包多平台的应用程序,.ico 文件是 Windows 特定的格式。对于 macOS 和 Linux,你可能需要提供其他格式的图标,如 .icns(macOS)或 .png(Linux)。然而,PyInstaller 目前仅支持在 Windows 上嵌入图标,其他平台上的图标可能需要在应用程序内部处理。

如果你的应用程序在多个平台上运行,并且你想要统一外观,可以考虑在应用程序的初始化代码中加载并设置图标。这通常涉及在你的主窗口或主应用实例上设置图标属性。

4..spec 文件的参数应用

当你使用 pyinstaller 命令时,如果不带任何关于 .spec 文件的参数,PyInstaller 会自动生成一个默认的 .spec 文件并基于此文件构建你的应用。这意味着你之前手动修改的 .spec 文件将不会被使用,而是会被覆盖。

要确保使用你修改过的 .spec 文件,你应该在运行 pyinstaller 命令时明确指定该文件。这可以通过在命令行中加入 .spec 文件的路径来完成。

例如,如果修改过的 .spec 文件叫做 composer1.7.spec 并且位于当前工作目录下,你应该使用以下命令:

pyinstaller composer1.7.spec

或者如果 .spec 文件位于其他目录中,你需要提供完整的路径:

pyinstaller /path/to/composer1.7.spec

这样,PyInstaller 将会读取你指定的 .spec 文件,并根据其中的配置构建你的应用程序。确保 .spec 文件中包含了正确的配置,比如我们之前讨论的

datas 参数,以便正确地包含图标文件和其他必要的资源。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。