杰瑞科技汇

python pyinstall打包

目录

  1. PyInstaller 简介
  2. 安装 PyInstaller
  3. 基本打包命令
  4. 常用参数详解
    • -F / --onefile (单文件模式)
    • -D / --onedir (目录模式)
    • -w / --windowed (无控制台窗口)
    • -i / --icon (设置图标)
    • --add-data (添加非代码文件)
    • --hidden-import (隐式导入)
    • --clean (清理临时文件)
  5. 完整打包流程示例
  6. 常见问题与解决方案
    • 打包后的文件太大?
    • 程序运行后闪退?
    • 打包后找不到资源文件(如图片、配置文件)?
    • 如何打包带控制台窗口的 GUI 程序?

PyInstaller 简介

PyInstaller 是一个跨平台的打包工具,它可以将 Python 应用程序及其所有依赖项(包括 Python 解释器)捆绑在一起,生成一个独立的可执行文件。

python pyinstall打包-图1
(图片来源网络,侵删)

优点:

  • 简单易用:命令行操作,几条命令即可完成。
  • 跨平台:支持 Windows, macOS, Linux。
  • 无需安装环境:打包后的 .exe 文件可以在任何同 Windows 版本的电脑上运行,无需预先安装 Python。

工作原理: PyInstaller 并不是将代码编译成机器码,而是将你的脚本、所有需要的库以及一个轻量级的 Python 解释器打包在一起,当用户运行 .exe 文件时,它会临时解压文件到系统临时目录,然后启动嵌入的 Python 解释器来运行你的脚本。


安装 PyInstaller

在打包之前,首先需要确保你已经安装了 PyInstaller,打开你的终端或命令提示符,运行以下命令:

pip install pyinstaller

基本打包命令

假设你有一个名为 my_app.py 的 Python 脚本。

python pyinstall打包-图2
(图片来源网络,侵删)

最简单的打包命令是:

pyinstaller my_app.py

执行后,PyInstaller 会在你的项目目录下创建三个文件夹:

  • build/:存放打包过程中的临时文件,可以删除。
  • dist/:存放最终生成的可执行文件和相关依赖。
  • my_app.spec:一个 PyInstaller 的配置文件,用于高级定制。

默认情况下,PyInstaller 会生成目录模式的打包文件,即 dist/my_app 文件夹,里面包含了可执行文件和所有依赖的 .dll.so 文件。


常用参数详解

为了更好地控制打包过程,你需要了解一些常用参数。

-F / --onefile (单文件模式)

将所有东西打包成一个单独的 .exe 文件,优点是方便分发,缺点是首次运行速度较慢(因为需要解压),且如果程序频繁读写临时文件,可能会被安全软件误报。

pyinstaller -F my_app.py

执行后,在 dist 目录下会生成一个 my_app.exe 文件。

-D / --onedir (目录模式)

将可执行文件和所有依赖库放在一个文件夹中,这是默认模式,优点是启动快,缺点是文件数量多。

pyinstaller -D my_app.py

-w / --windowed (无控制台窗口)

运行程序时不会弹出黑色的命令行窗口,这对于 GUI 应用程序(如使用 Tkinter, PyQt, Kivy 开发的)非常有用。

pyinstaller -w my_app.py

-i / --icon (设置图标)

为你的 .exe 文件设置一个自定义图标,图标文件必须是 .ico 格式。

pyinstaller -i my_icon.ico -F my_app.py

--add-data (添加非代码文件)

如果你的程序需要依赖一些外部文件,比如图片、配置文件、数据库等,就需要使用这个参数。

语法:--add-data <源路径>:<目标路径>

  • Windows:路径分隔符用
  • macOS / Linux:路径分隔符用

示例: 假设你的项目结构如下:

my_project/
├── my_app.py
└── assets/
    └── logo.png

my_app.py 中,你可能通过相对路径 assets/logo.png 来访问这个图片。

打包时,你需要将 assets 文件夹添加进去:

# Windows
pyinstaller --add-data "assets;assets" -F my_app.py
# macOS / Linux
pyinstaller --add-data "assets:assets" -F my_app.py

打包后,PyInstaller 会将这些数据文件复制到可执行文件的运行目录下,在代码中,你需要使用 sys._MEIPASS 来找到这些文件的正确路径。

--hidden-import (隐式导入)

有时,你的代码中可能通过字符串或动态导入的方式加载一个模块,PyInstaller 无法静态分析到这种依赖关系,这时就需要用 --hidden-import 来手动告诉 PyInstaller 需要包含这个模块。

# pandas 内部可能会隐式导入 'xlrd'
pyinstaller --hidden-import=xlrd -F my_app.py

--clean (清理临时文件)

在每次打包前,清理掉 builddist 目录以及 .spec 文件,这是一个好习惯,可以避免因旧文件导致的问题。

pyinstaller --clean -F my_app.py

完整打包流程示例

假设我们要打包一个简单的带 GUI 和图标的程序。

项目结构:

hello_app/
├── hello_app.py
├── assets/
│   └── icon.ico
└── assets/
    └── bg.jpg

hello_app.py 代码:

import tkinter as tk
from PIL import Image, ImageTk # 需要安装 Pillow: pip install Pillow
import sys
import os
def get_resource_path(relative_path):
    """ 获取资源的绝对路径,兼容 PyInstaller 打包后的路径 """
    try:
        # PyInstaller 创建一个临时文件夹 _MEIPASS,并将路径存储在 _MEIPASS 中
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)
root = tk.Tk()"Hello PyInstaller")
root.geometry("400x300")
# 设置图标
icon_path = get_resource_path("assets/icon.ico")
root.iconbitmap(icon_path)
# 加载背景图片
bg_image_path = get_resource_path("assets/bg.jpg")
bg_image = Image.open(bg_image_path)
bg_photo = ImageTk.PhotoImage(bg_image)
bg_label = tk.Label(root, image=bg_photo)
bg_label.place(x=0, y=0, relwidth=1, relheight=1)
# 添加一个标签
label = tk.Label(root, text="打包成功!", font=("Arial", 24), bg="white")
label.pack(pady=50)
root.mainloop()

打包步骤:

  1. 安装依赖

    pip install pillow pyinstaller
  2. 打开终端,进入 hello_app 目录

  3. 执行打包命令 这个命令会:

    • (--clean) 清理旧文件。
    • (-F) 打包成单个 .exe 文件。
    • (-w) 不显示控制台窗口。
    • (-i) 设置图标。
    • (--add-data) 添加图标和背景图片资源。
    # Windows 命令
    pyinstaller --clean -F -w -i assets/icon.ico --add-data "assets;assets" hello_app.py
  4. 运行 打包完成后,进入 dist 目录,你会看到一个 hello_app.exe 文件,双击它,一个独立的 GUI 程序就会运行起来,并且有自定义的图标和背景图。


常见问题与解决方案

打包后的文件太大?

这是最常见的问题,原因是你打包了整个 Python 标准库和一些你并不需要的库。

  • 解决方案
    1. 使用 UPX 压缩:PyInstaller 可以使用 UPX 工具来压缩可执行文件和依赖库,你需要先安装 UPX (下载地址),然后将 UPX 的路径添加到系统环境变量 PATH 中,打包时加上 --upx-dir 参数。
      pyinstaller -F --upx-dir="C:\path\to\upx" my_app.py
    2. 排除不必要的模块:通过 .spec 文件可以更精细地控制,运行 pyi-makespec my_app.py 生成 .spec 文件,然后编辑它,在 EXE()COLLECT() 对象中添加 excludes 参数。
      # my_app.spec
      a = Analysis(['my_app.py'],
                   ...
                   excludes=['tkinter', 'unittest'], # 排除这些模块
                   ...)

程序运行后闪退?

闪退通常意味着程序在启动时遇到了错误,但因为使用了 -w 参数,错误信息被隐藏了。

  • 解决方案
    1. 先去掉 -w 参数重新打包:这样会带有一个控制台窗口,运行 .exe 文件,查看控制台输出的错误信息。
    2. 根据错误信息解决问题:常见的错误包括:
      • 缺少隐式导入:使用 --hidden-import 添加缺失的模块。
      • 找不到资源文件:检查 --add-data 路径是否正确,并在代码中使用 sys._MEIPASS 获取资源路径。

打包后找不到资源文件(如图片、配置文件)?

这是因为打包后的可执行文件运行时,工作目录已经改变,直接使用相对路径 ./assets/image.png 是找不到文件的。

  • 解决方案: 如上例所示,创建一个辅助函数 get_resource_path 来获取资源的绝对路径,这个函数会检查程序是否被 PyInstaller 打包,并返回正确的资源路径。

如何打包带控制台窗口的 GUI 程序?

有些时候,即使程序是 GUI,你也希望它能弹出一个控制台窗口来打印调试信息。

  • 解决方案: 使用 --console 参数(或 -c),这是默认行为,但如果之前用了 -w,现在想改回来,就需要明确指定。
    pyinstaller --console -F my_app.py

    这样,运行 .exe 时就会先弹出一个黑色的控制台窗口,GUI 界面会出现在上面。


需求 命令 (Windows)
最简单打包 pyinstaller my_app.py
单文件模式 pyinstaller -F my_app.py
无控制台窗口 pyinstaller -w my_app.py
自定义图标 pyinstaller -i my_icon.ico my_app.py
添加资源文件 pyinstaller --add-data "src;dest" my_app.py
清理并打包 pyinstaller --clean -F my_app.py
调试闪退问题 pyinstaller --console my_app.py (先不带 -w 运行)

掌握这些基本命令和参数,你就可以应对绝大多数 Python 程序的打包需求了,对于更复杂的项目,可以深入研究 .spec 文件,它能提供更强大的定制能力。

分享:
扫描分享到社交APP
上一篇
下一篇