点击➡下载地址
import os
import subprocess
import sys
import time
import tkinter as tk
from tkinter import ttk, filedialog, scrolledtext
# 尝试导入psutil,如果不存在则在后续代码中处理
try:
import psutil
import PyInstaller
import PIL
import pandas
import openpyxl
HAS_PSUTIL = True
except ImportError:
HAS_PSUTIL = False
class PackageGUI:
def __init__(self):
self.root = tk.Tk()
self.root.title("py代码打包ExEh工具")
self.root.geometry("800x600")
# 创建主框架
self.main_frame = ttk.Frame(self.root, padding="10")
self.main_frame.pack(fill=tk.BOTH, expand=True)
# 输入文件选择
ttk.Label(self.main_frame, text="输入文件:").pack(anchor=tk.W)
self.input_frame = ttk.Frame(self.main_frame)
self.input_frame.pack(fill=tk.X, pady=5)
self.input_path = tk.StringVar()
ttk.Entry(self.input_frame, textvariable=self.input_path).pack(side=tk.LEFT, fill=tk.X, expand=True)
ttk.Button(self.input_frame, text="浏览", command=self.select_input).pack(side=tk.RIGHT)
# 输出目录选择
ttk.Label(self.main_frame, text="输出目录:").pack(anchor=tk.W)
self.output_frame = ttk.Frame(self.main_frame)
self.output_frame.pack(fill=tk.X, pady=5)
self.output_path = tk.StringVar()
ttk.Entry(self.output_frame, textvariable=self.output_path).pack(side=tk.LEFT, fill=tk.X, expand=True)
ttk.Button(self.output_frame, text="浏览", command=self.select_output).pack(side=tk.RIGHT)
# 输出文件名称
ttk.Label(self.main_frame, text="输出文件名称:").pack(anchor=tk.W)
self.output_name_frame = ttk.Frame(self.main_frame)
self.output_name_frame.pack(fill=tk.X, pady=5)
self.output_name = tk.StringVar(value="文件名称批量获取工具")
ttk.Entry(self.output_name_frame, textvariable=self.output_name).pack(side=tk.LEFT, fill=tk.X, expand=True)
# 调试模式选项
self.debug_mode = tk.BooleanVar()
ttk.Checkbutton(self.main_frame, text="调试模式", variable=self.debug_mode).pack(anchor=tk.W, pady=5)
# 日志显示区域
ttk.Label(self.main_frame, text="打包日志:").pack(anchor=tk.W)
self.log_text = scrolledtext.ScrolledText(self.main_frame, height=20)
self.log_text.pack(fill=tk.BOTH, expand=True, pady=5)
# 按钮区域
self.button_frame = ttk.Frame(self.main_frame)
self.button_frame.pack(fill=tk.X, pady=10)
ttk.Button(self.button_frame, text="开始打包", command=self.start_package).pack(side=tk.RIGHT)
def select_input(self):
filename = filedialog.askopenfilename(filetypes=[("Python Files", "*.py")])
if filename:
self.input_path.set(filename)
def select_output(self):
dirname = filedialog.askdirectory()
if dirname:
self.output_path.set(dirname)
def log(self, message):
self.log_text.insert(tk.END, message + "\n")
self.log_text.see(tk.END)
self.root.update()
def start_package(self):
self.log("开始打包流程...")
# 检查必要的库
if not self.check_requirements():
return
# 打包应用
if self.package_app():
self.log("\n打包过程完成!您可以分发生成的exe文件给其他用户使用。")
else:
self.log("\n打包过程未成功完成,请检查上述错误信息。")
def check_requirements(self):
# 检查并安装必要的库
try:
import PyInstaller
self.log("检测到PyInstaller已安装")
except ImportError:
self.log("无法继续打包过程,请手动安装PyInstaller后重试。")
return False
try:
import PIL
self.log("检测到Pillow已安装")
except ImportError:
self.log("警告:Pillow库安装失败,可能无法正确处理自定义图标。")
try:
import pandas
import openpyxl
self.log("检测到pandas和openpyxl已安装")
except ImportError:
self.log("警告:pandas或openpyxl库安装失败,可能无法正确支持Excel导出功能。")
return True
def check_icon_file(self):
"""检查图标文件是否存在"""
icon_path = os.path.join(os.path.dirname(self.input_path.get()), "app_icon.ico")
return os.path.exists(icon_path)
def package_app(self):
input_file = self.input_path.get()
output_dir = self.output_path.get()
output_name = self.output_name.get()
if not input_file or not os.path.exists(input_file):
self.log("错误:请选择有效的输入文件")
return False
if not output_dir:
self.log("错误:请选择输出目录")
return False
if not output_name:
self.log("错误:请输入输出文件名称")
return False
# 构建PyInstaller命令
cmd = [
sys.executable,
"-m",
"PyInstaller",
f"--name={output_name}",
"--onefile",
"--hidden-import=pandas",
"--hidden-import=openpyxl",
f"--distpath={output_dir}"
]
if self.debug_mode.get():
cmd.extend(["--console", "--debug=all"])
else:
cmd.append("--windowed")
# 检查图标文件
if self.check_icon_file():
cmd.append("--icon=" + os.path.join(os.path.dirname(input_file), "app_icon.ico"))
cmd.append(input_file)
try:
# 执行打包命令
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
# 实时显示输出
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if output:
self.log(output.strip())
return process.poll() == 0
except Exception as e:
self.log(f"打包过程出错: {e}")
return False
def main():
app = PackageGUI()
app.root.mainloop()
if __name__ == "__main__":
main()