写了一个简单的pyinstaller把py打包成exe的GUI程序
源代码:
static/image/hrline/4.gif
感觉我写的总是有点像屎山{:10_282:}
from tkinter import *
from tkinter import filedialog, messagebox, ttk
import os
import subprocess
import sys
import shutil
import glob
class App(Tk):
def __init__(self):
super().__init__()
self.title("Pytoexe")
self.top = None
self.cmd = ""
self.run()
def initialize(self):
self.os_type = sys.platform
self.label1 = Label(self, text="请输入Python文件路径")
self.label1.grid(row=0, column=0, padx=5, pady=5, sticky='nsew')
self.entry1 = Entry(self, width=40)
self.entry1.grid(row=0, column=1, padx=5, pady=5, sticky='nsew')
self.button1 = Button(self, text="选择文件", command=lambda :self.select_file(self.entry1))
self.button1.grid(row=1, column=0, padx=5, pady=5, sticky='w')
self.button2 = Button(self, text="进行打包", command=self.package)
self.button2.grid(row=1, column=1, padx=5, pady=5, sticky='e')
yesno = messagebox.askyesno(title="提示", message="是否已配置Python环境?")
if not yesno:
messagebox.showinfo(title="提示", message="使用该程序请先配置Python环境!")
self.destroy()
else:
messagebox.showinfo(title="提示", message="请继续使用。")
def package(self):
if not self.top:
if os.path.exists(self.entry1.get()):
self.cmd = f"pyinstaller --clean \"{self.entry1.get()}\""
self.create_toplevel()
else:
messagebox.showwarning(title="警告", message="请输入正确的Python文件路径!!!")
else:
messagebox.showwarning(title="警告", message="请先关闭当前窗口!!!")
def create_toplevel(self):
self.top = Toplevel(master=self)
self.tlb1 = Label(self.top, text="请输入exe文件名")
self.tlb1.grid(row=0, column=0, padx=5, pady=5, sticky='nsew')
self.tentry1 = Entry(self.top, width=30)
self.tentry1.grid(row=0, column=1, padx=5, pady=5, sticky='nsew')
self.tlb2 = Label(self.top, text="请输入exe文件路径")
self.tlb2.grid(row=1, column=0, padx=5, pady=5, sticky='nsew')
self.tentry2 = Entry(self.top, width=30)
self.tentry2.grid(row=1, column=1, padx=5, pady=5, sticky='nsew')
self.tbutton1 = Button(self.top, text="选择路径", command=self.tbutton1_callback)
self.tbutton1.grid(row=1, column=2, padx=5, pady=5, sticky='nsew')
self.tlb3 = Label(self.top, text="请输入依赖文件路径")
self.tlb3.grid(row=2, column=0, padx=5, pady=5, sticky='nsew')
self.tentry3 = Entry(self.top, width=30)
self.tentry3.grid(row=2, column=1, padx=5, pady=5, sticky='nsew')
self.tbutton2 = Button(self.top, text="选择路径", command=self.tbutton2_callback)
self.tbutton2.grid(row=2, column=2, padx=5, pady=5, sticky='nsew')
self.tlb4 = Label(self.top, text="请输入图标路径")
self.tlb4.grid(row=3, column=0, padx=5, pady=5, sticky='nsew')
self.tentry4 = Entry(self.top, width=30)
self.tentry4.grid(row=3, column=1, padx=5, pady=5, sticky='nsew')
self.tbutton3 = Button(self.top, text="添加图标", command=self.tbutton3_callback)
self.tbutton3.grid(row=3, column=2, padx=5, pady=5, sticky='nsew')
self.tlb5 = Label(self.top, text="请选择需要资源的模块名称")
self.tlb5.grid(row=4, column=0, padx=5, pady=5, sticky='nsew')
choices = ['tkinter', 'PyQt5', 'PyQt6', 'PySide2', 'PySide6', 'mmatplotlib', 'skimage', 'pandas', 'babel']
self.tcombox = ttk.Combobox(self.top, values=choices, state="readonly", width=30)
self.tcombox.set("请选择模块")
self.tcombox.bind("<<ComboboxSelected>>", self.cb_on_select)
self.tcombox.grid(row=4, column=1, padx=5, pady=5, sticky='nsew')
self.tframe = Frame(self.top)
self.tframe.grid(row=5, column=0, columnspan=2, padx=5, pady=5, sticky='nsew')
self.tcheck1 = Checkbutton(self.tframe, text="是否单个文件", command=self.check1_callback)
self.tcheck1.grid(row=0, column=0, padx=5, pady=5, sticky='nsew')
self.tcheck2 = Checkbutton(self.tframe, text="是否更改文件名", command=self.check2_callback)
self.tcheck2.grid(row=0, column=1, padx=5, pady=5, sticky='nsew')
self.var1 = IntVar()
self.tcheck3 = Checkbutton(self.tframe, text="是否更改文件路径", variable=self.var1, command=self.check3_callback)
self.tcheck3.grid(row=0, column=2, padx=5, pady=5, sticky='nsew')
self.tcheck4 = Checkbutton(self.tframe, text="是否为GUI程序", command=self.check4_callback)
self.tcheck4.grid(row=1, column=0, padx=5, pady=5, sticky='nsew')
self.var2 = IntVar()
self.tcheck5 = Checkbutton(self.tframe, text="是否有依赖文件", variable=self.var2, command=self.check5_callback)
self.tcheck5.grid(row=1, column=1, padx=5, pady=5, sticky='nsew')
self.var3 = IntVar()
self.tcheck6 = Checkbutton(self.tframe, text="是否需要模块资源", variable=self.var3, command=self.check6_callback)
self.tcheck6.grid(row=1, column=2, padx=5, pady=5, sticky='nsew')
self.tbutton_package = Button(self.top, text="运行", command=self.run_cmd)
self.tbutton_package.grid(row=5, column=2, padx=5, pady=5, sticky='nsew')
def tbutton1_callback(self):
self.select_file(self.tentry2)
if self.tentry2.get():
self.var1.set(1)
self.check3_callback()
def tbutton2_callback(self):
self.select_file(self.tentry3)
if self.tentry3.get():
self.var2.set(1)
self.check5_callback()
def tbutton3_callback(self):
self.select_file(self.tentry4)
if self.tentry4.get():
self.ico_callback()
def ico_callback(self):
if "--icon" in self.cmd:
self.cmd = self.cmd.replace(f'--icon "{self.tentry4.get()}" ', '')
else:
if self.tentry4.get():
self.cmd = self.cmd.replace("pyinstaller", f"pyinstaller --icon \"{self.tentry4.get()}\"")
def del_callback(self):
for path in ['build', '__pycache__']:
shutil.rmtree(path, ignore_errors=True)
for f in glob.glob('*.spec'):
os.remove(f)
def run_cmd(self):
"""执行程序"""
if not os.path.exists(self.tentry2.get()):
messagebox.showwarning(title="警告", message="请输入正确的exe文件路径!!!")
return
if self.cmd:
subprocess.run('python -m pip install --upgrade pip', shell=True)
subprocess.run('python -m pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple', shell=True)
subprocess.run('python -m pip install -U pyinstaller', shell=True)
subprocess.run(self.cmd, shell=True)
self.del_callback()
rt = messagebox.askokcancel("提示", "打包完成!!!\n是否关闭程序")
if rt:
exit()
else:
self.top.destroy()
self.top = None
def check1_callback(self):
if "--onefile" in self.cmd:
_ = self.cmd.replace("--onefile ", "")
else:
_ = self.cmd.replace("pyinstaller", "pyinstaller --onefile")
self.cmd = _
def check2_callback(self):
if "--name" in self.cmd:
self.cmd = self.cmd.replace(f"--name {self.tentry1.get()} ", "")
else:
if self.tentry1.get():
self.cmd = self.cmd.replace("pyinstaller", f"pyinstaller --name \"{self.tentry1.get()}\"")
def check3_callback(self):
if "--distpath" in self.cmd:
self.cmd = self.cmd.replace(f"pyinstaller --distpath=\"{self.tentry2.get()}\" ", "")
else:
if self.tentry2.get():
self.cmd = self.cmd.replace("pyinstaller", f"pyinstaller --distpath=\"{self.tentry2.get()}\"")
def check4_callback(self):
if "--windowed" in self.cmd:
_ = self.cmd.replace("--windowed ", "")
else:
_ = self.cmd.replace("pyinstaller", "pyinstaller --windowed")
self.cmd = _
def check5_callback(self):
self.datas = self.getdatas()
if "--add-data" in self.cmd:
self.cmd = self.cmd.replace(f'--add-data="{self.datas}" ', '')
else:
if self.tentry3.get():
self.cmd = self.cmd.replace("pyinstaller", f"pyinstaller --add-data=\"{self.datas}\"")
print(self.cmd)
def check6_callback(self):
if "--collect-data" in self.cmd:
self.cmd = self.cmd.replace(f"--collect-data {self.tcombox.get()}", "")
else:
if self.tcombox.get() != "请选择模块":
self.cmd = self.cmd.replace("pyinstaller", f"pyinstaller --collect-data {self.tcombox.get()}")
def cb_on_select(self, event):
if self.tcombox.get() != "请选择模块":
self.var3.set(1)
self.check6_callback()
def getdatas(self):
datas = ""
file_path = self.tentry3.get()
relative_path = file_path.replace(os.path.dirname(self.entry1.get()), "").replace("/", "")
if self.os_type == "win32":
datas = f"{file_path}/*;{relative_path}"
else:
datas = f"{file_path}/*:{relative_path}"
return datas
def select_file(self, entry=None):
if entry == self.entry1:
if self.top:
messagebox.showwarning(title="警告", message="请先关闭当前窗口!!!")
return
file_path = filedialog.askopenfilename(filetypes=[("Python Files", "*.py")])
elif entry == self.tentry4:
file_path = filedialog.askopenfilename(filetypes=[("icon Files", "*.ico")])
else:
file_path = filedialog.askdirectory()
entry.delete(0, END)
entry.insert(0, file_path)
def run(self):
self.initialize()
self.mainloop()
if __name__ == "__main__":
app = App()
没有把代码打包成exe文件了,不知道为什么打包成exe之后运行打包py文件总是出问题,用代码运行又没问题,{:9_241:}不知道还有没有什么隐藏的bug,一些简单的py程序应该还是能打包的
static/image/hrline/4.gif
打包的过程可能会有点久,
注意这里点击确定没有关闭的话就是打包出错了{:10_304:}
没有鱼币了,发完了{:10_266:}
这年头还自己写代码,羡慕{:13_445:} 不错不错~~ {:10_256:} 真正的石山还得看我,6层If你顶的住吗{:10_256:} {:9_229:} 666 挺实用的哈哈 看不懂看不懂 膜拜一下{:10_266:} 膜拜膜拜 {:10_328:} {:10_297:} {:5_100:}{:5_109:}{:5_107:}
页:
[1]