前言
虽然很多开发者专注于 Web 开发,但对 Python 的众多开源项目一直都很关注。像 Stable Diffusion 的 AI 绘画,以及 So-VITS-SVC 音色替换等项目的源码部署文档通常比较完善。尽管如此,对于刚入门或本地环境搭建容易踩坑的同学来说,直接运行源码往往不太友好。针对这一现象,网上已有各种解决方案提供一键部署,无需安装 Python 环境,无需下载各种依赖包,点击 exe 即可使用。
本文详细介绍了如何使用 PyInstaller 将 Python 脚本打包为独立的可执行文件,并利用 Inno Setup Compiler 创建具备安装向导和卸载功能的安装包。内容涵盖虚拟环境配置、GUI 程序编写规范、打包参数详解、Inno Setup 脚本定制以及常见依赖问题的解决方案,旨在帮助开发者实现软件的便捷分发与环境隔离部署。

虽然很多开发者专注于 Web 开发,但对 Python 的众多开源项目一直都很关注。像 Stable Diffusion 的 AI 绘画,以及 So-VITS-SVC 音色替换等项目的源码部署文档通常比较完善。尽管如此,对于刚入门或本地环境搭建容易踩坑的同学来说,直接运行源码往往不太友好。针对这一现象,网上已有各种解决方案提供一键部署,无需安装 Python 环境,无需下载各种依赖包,点击 exe 即可使用。
那么这些方案是如何实现的呢?很多人会想到 PyInstaller。它确实可以解决整体环境的打包问题,但有时候一些图标和依赖文件需要放在一起才能正常使用,类似于绿色桌面工具。有没有方法对这个进一步封装,就是点击 exe 后需要安装,然后安装后才是项目的文件,还可以卸载?答案是使用 Inno Setup Compiler。接下来我将用一个 GUI 的小 demo 完成 exe 打包和进一步安装打包。

为了确保打包过程顺利,建议准备以下环境:
建议使用 Conda 创建独立的虚拟环境,避免系统全局环境冲突。
tools_env。
# 1. 创建环境
conda create -n tools_env python=3.8
# 2. 进入环境
conda activate tools_env
# 3. 安装 pyinstaller
pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple
以下是一个简单的批量重命名工具示例,使用了 Tkinter 构建界面。注意清理了原有的推广信息。
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import os
class Application(tk.Tk):
def __init__(self):
super().__init__()
self.title("文件批量重命名工具")
# 确保 iconbitmap 路径正确,打包时需放入同一目录
try:
self.iconbitmap('logo.ico')
except:
pass
self.geometry("600x370") # 设置固定的窗口大小
self.resizable(False, False) # 禁止调整窗口大小
self.style = ttk.Style(self)
self.main_color = self.cget("bg")
self.style.configure("TEntry",
padding=6,
relief="flat",
background="#0078d7",
foreground="black",
font=("Arial", 12, "bold"))
self.style.configure("TLabel",
font=("Arial", 12, "bold"))
self.style.configure("TButton",
padding=6,
font=("Arial", 12))
self.create_widgets()
def create_widgets(self):
self.path_label = ttk.Label(self, text='绝对路径:')
self.path_label.grid(row=0, sticky=tk.W, pady=30, padx=20)
self.path = tk.StringVar()
self.path_entry = ttk.Entry(self, width=60, textvariable=self.path)
self.path_entry.grid(row=0, column=1, sticky=tk.E, pady=5)
self.rename_label = ttk.Label(self, text='修改名称:')
self.rename_label.grid(row=1, sticky=tk.W, pady=5, padx=20)
self.rename = tk.StringVar()
self.rename_entry = ttk.Entry(self, width=60, textvariable=self.rename)
self.rename_entry.grid(row=1, column=1, sticky=tk.E, pady=5)
self.msg_text = tk.Text(self, height=2, width=60, wrap='none')
self.msg_text.grid(row=2, column=1, sticky=tk.W, pady=15)
self.msg_text.configure(bd=0, relief="solid", bg=self.main_color)
ttk.Button(self, text='确认修改', command=self.start_program).grid(row=3, column=1, sticky=tk.W, pady=20, padx=120)
ttk.Button(self, text='关于', command=self.about).grid(row=4, column=1, sticky=tk.W, padx=120)
def start_program(self):
path = self.path.get()
rename = self.rename.get()
if path == "" or rename == "":
messagebox.showwarning("警告", "输入框不能为空!")
return
if not os.path.isdir(path):
messagebox.showwarning("警告", "绝对路径不正确!")
return
i = 0
FileList = os.listdir(path)
for files in FileList:
oldDirPath = os.path.join(path, files)
self.msg_text.delete(1.0, tk.END)
self.msg_text.insert(tk.END, f"处理中:{oldDirPath}")
if os.path.isdir(oldDirPath):
continue # 简化逻辑,仅处理文件
fileName = os.path.splitext(files)[0]
fileType = os.path.splitext(files)[1].lower()
newDirPath = os.path.join(path, f"{rename}_{i}{fileType}")
try:
os.rename(oldDirPath, newDirPath)
i += 1
except Exception as e:
print(f"重命名失败:{files}, 错误:{e}")
messagebox.showinfo("信息", "操作完成!")
def about(self):
messagebox.showinfo("关于", "工具:批量修改文件 1.0\n作者:技术团队")
def quit_program(self):
self.destroy()
if __name__ == "__main__":
app = Application()
app.mainloop()
使用 PyInstaller 将脚本转换为可执行文件。命令如下:
pyinstaller -F -w Application.py --icon=logo.ico
参数说明:
--icon=图标路径:指定 exe 图标。-F:打包成一个 exe 文件。-w:使用窗口模式,无控制台黑框。-c:使用控制台模式,有黑框。-D:创建一个目录,里面包含 exe 以及其他一些依赖性文件。如果修改了代码需要重新打包,建议删除上一次生成的 .spec 后缀文件,以免配置冲突。打包成功后,控制台会显示 Building EXE from EXE-00.toc completed successfully。根目录下的 dist 文件夹即为打包后的文件包,里面包含了 exe 及所需的动态链接库和图片等资源。


Inno Setup 是一款免费且强大的 Windows 安装程序制作软件。我们需要编写一个脚本文件(.iss)来定义安装过程。
打开 Inno Setup Compiler,选择新建脚本向导,填写应用程序名称、版本号等信息。

在文件选择步骤中,指向之前 PyInstaller 生成的 dist 文件夹中的 exe 文件,并勾选其他需要的资源文件。

设置安装程序的标题、公司名称以及安装图标。

选择编译后的安装包输出路径。在生成前还可以设置协议条款等高级选项。

点击运行按钮开始生成安装包。

安装完成后,安装目录内会自带卸载程序,用户可以在'控制面板'或'设置'中轻松卸载。

为了更灵活地控制安装过程,我们可以手动编辑 .iss 脚本文件。以下是标准脚本结构的详细说明:
[Setup]
AppName=My Program
AppVersion=1.0
DefaultDirName={autopf}\MyProgram
DefaultGroupName=My Program
OutputDir=output
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Files]
Source: "dist\*.exe"; DestDir: "{app}"
Source: "dist\*.dll"; DestDir: "{app}"
Source: "images\*.*"; DestDir: "{app}\images"
[Icons]
Name: "{group}\{cm:UninstallProgram,MyProgram}"; Filename: "{uninstallexe}"
Name: "{autodesktop}\MyProgram"; Filename: "{app}\myprogram.exe"
[Run]
Filename: "{app}\myprogram.exe"; Description: "{cm:LaunchProgram,MyProgram}"; Flags: nowait postinstall skipifsilent
{app} 代表用户选择的目录,{autopf} 代表 Program Files。Source 是源路径,DestDir 是目标路径。支持通配符。{group} 代表开始菜单组,{autodesktop} 代表桌面。nowait 表示不等待程序结束,postinstall 表示在安装结束时运行。如果在运行 exe 时提示缺少 MSVCP140.dll 等文件,说明缺少 Visual C++ 运行库。解决方法是在 PyInstaller 打包时添加 --add-data 参数引入必要的 DLL,或者在 Inno Setup 脚本中添加 VC++ 运行库的安装逻辑。
由于未签名的 exe 容易被杀毒软件拦截。建议申请代码签名证书(Authenticode)对 exe 进行签名,或者在发布前告知用户添加信任白名单。
PyInstaller 默认会将所有依赖打包进去。可以使用 --onefile 优化,或者检查是否有不必要的模块被引入。对于大型项目,考虑使用 --onedir 模式,体积会更小且加载更快。
确保源代码文件保存为 UTF-8 格式。在 PyInstaller 打包时,如果遇到中文路径问题,可以尝试在脚本开头添加 # -*- coding: utf-8 -*-。
通过结合 PyInstaller 和 Inno Setup Compiler,开发者可以将 Python 项目转化为专业的 Windows 应用程序。这不仅解决了环境依赖问题,还提升了用户体验。掌握上述流程后,您可以轻松分发自己的工具软件,无需用户具备编程背景即可使用。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online