Skip to content

Commit 7a4954a

Browse files
committed
更新:
1. 添加 upx 配置项 2. 添加高级配置界面切换(高级选项功能待开发) 3. 添加构建配置文件
1 parent 8072ec1 commit 7a4954a

File tree

5 files changed

+168
-55
lines changed

5 files changed

+168
-55
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ MANIFEST
3131
# Usually these files are written by a python script from a template
3232
# before PyInstaller builds the exe, so as to inject date/other infos into it.
3333
*.manifest
34-
*.spec
34+
# *.spec
3535

3636
# Installer logs
3737
pip-log.txt
@@ -127,3 +127,6 @@ dmypy.json
127127

128128
# Pyre type checker
129129
.pyre/
130+
131+
# Test
132+
test/

build.sh

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
# _*_ coding:utf-8 _*_
22

3-
cd src
43
pyinstaller \
54
--clean\
65
--noconfirm\
76
-w\
8-
--distpath=../dist\
9-
--workpath=../\
10-
build.spec
11-
cd ..
7+
build.spec

build.spec

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# -*- mode: python -*-
2+
3+
BLOCK_CIPHER = None
4+
APP_NAME = 'PyinstallerDesktop'
5+
APP_NAME_DISPLAY = 'Pyinstaller桌面客户端'
6+
APP_APP = 'PyinstallerDesktop.app'
7+
APP_COPYRIGHT = 'Copyright © 2020-2022 Jackson Dou All Rights Reserved'
8+
APP_VERSION = '0.0.2'
9+
SCRIPTS = ['src/app.py']
10+
BINARIES = []
11+
DATAS = []
12+
HIDDEN_IMPORTS = [] # 源文件的依赖模块
13+
HOOKSPATH = []
14+
EXCLUDES = [] # 不需要打包的模块
15+
RUNTIME_HOOKS = []
16+
BUNDLE_IDENTIFIER = 'org.pythub.app.pyinstaller-desktop' # 一般情况下Bundle ID的格式为:com.公司名称.项目名称
17+
UPX = True # 如果有UPX安装(执行Configure.py时检测),会压缩执行文件(Windows系统中的DLL也会)
18+
PATHEX = ['src']
19+
20+
a = Analysis(SCRIPTS,
21+
pathex=PATHEX,
22+
binaries=BINARIES,
23+
datas=DATAS,
24+
hiddenimports=HIDDEN_IMPORTS,
25+
hookspath=HOOKSPATH,
26+
runtime_hooks=RUNTIME_HOOKS,
27+
excludes=EXCLUDES,
28+
win_no_prefer_redirects=False,
29+
win_private_assemblies=False,
30+
cipher=BLOCK_CIPHER,
31+
noarchive=False
32+
)
33+
pyz = PYZ(a.pure, a.zipped_data, cipher=BLOCK_CIPHER)
34+
exe = EXE(
35+
pyz,
36+
a.scripts, [],
37+
exclude_binaries=True,
38+
name=APP_NAME,
39+
debug=False,
40+
bootloader_ignore_signals=False,
41+
strip=False,
42+
upx=UPX,
43+
console=False
44+
)
45+
coll = COLLECT(
46+
exe,
47+
a.binaries,
48+
a.zipfiles,
49+
a.datas,
50+
strip=False,
51+
upx=UPX,
52+
name=APP_NAME
53+
)
54+
app = BUNDLE(
55+
coll,
56+
name=APP_APP,
57+
icon=None,
58+
bundle_identifier=BUNDLE_IDENTIFIER,
59+
info_plist={
60+
'CFBundleName': APP_NAME,
61+
'CFBundleDisplayName': APP_NAME_DISPLAY,
62+
'CFBundleExecutable': APP_NAME,
63+
'CFBundlePackageType': 'APPL',
64+
'CFBundleSupportedPlatforms': ['MacOSX'],
65+
'CFBundleGetInfoString': "Jackson Dou",
66+
'CFBundleIdentifier': BUNDLE_IDENTIFIER,
67+
'CFBundleVersion': APP_VERSION,
68+
'CFBundleInfoDictionaryVersion': APP_VERSION,
69+
'CFBundleShortVersionString': APP_VERSION,
70+
'NSHighResolutionCapable': True,
71+
'NSHumanReadableCopyright': APP_COPYRIGHT
72+
}
73+
)

src/app.py

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,27 @@
11
# -*- coding: utf-8 -*-
22

3-
from os import system
4-
from threading import Thread
53
from tkinter import Tk
6-
# from shlex import split
7-
# from subprocess import call
84

95
from utils import set_window_center
106
from view import View
117
# import PyInstaller
128
# import PyInstaller.__main__
139

14-
class App(View):
15-
def __init__(self, master=None):
16-
super(App, self).__init__()
17-
18-
def fn_build(self):
19-
'''生成可执行文件'''
20-
if not self.status_build:
21-
thread_build = Thread(target=self.fn_thread)
22-
thread_build.setDaemon(True)
23-
thread_build.start()
24-
else:
25-
self.label_status['text'] = '正在打包,请稍后再操作!'
26-
27-
def fn_thread(self):
28-
'''线程执行生成动作'''
29-
if len(self.entry_value_list[0].get()) == 0:
30-
self.label_status['text'] = '请选择源文件'
31-
return
32-
self.status_build = True
33-
cmd = self.fn_build_cmd()
34-
print(cmd)
35-
self.label_status['text'] = '正在打包,请稍等。。。'
36-
try:
37-
# PyInstaller.__main__.run(cmd)
38-
system(' '.join(cmd))
39-
# call(split(' '.join(cmd)), shell=True)
40-
self.status_build = False
41-
self.label_status['text'] = '打包成功!'
42-
except Exception as e:
43-
self.label_status['text'] = str(e)
44-
self.status_build = False
10+
11+
class App(Tk):
12+
'''
13+
App
14+
15+
应用程序主窗体,所有窗口、组件的根级窗口
16+
'''
17+
18+
def __init__(self):
19+
Tk.__init__(self)
20+
self.title('Pyinstaller Desktop')
21+
View(self)
22+
set_window_center(self)
23+
self.mainloop()
24+
4525

4626
if __name__ == '__main__':
47-
root = Tk()
48-
root.title('GUI应用生成器')
49-
App(root)
50-
set_window_center(root)
51-
root.mainloop()
27+
App()

src/view.py

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import os.path
44
from tkinter import (Button, Checkbutton, Entry, IntVar, Label, LabelFrame, StringVar, filedialog)
5-
5+
from os import system
6+
from threading import Thread
7+
from utils import set_window_center
68

79
class View(object):
810
def __init__(self, master=None):
@@ -12,13 +14,20 @@ def __init__(self, master=None):
1214

1315
def init_view(self):
1416
'''基本框架'''
15-
self.frm_project = LabelFrame(self.root, text='项目')
16-
self.frm_config = LabelFrame(self.root, text='配置')
17-
self.frm_operate = LabelFrame(self.root, text='操作')
18-
self.frm_status = LabelFrame(self.root, text='状态')
17+
self.frm_main = LabelFrame(self.root, borderwidth=0)
18+
self.frm_main.pack( side='left', fill='y')
19+
20+
self.frm_advance = LabelFrame(self.root, text='高级选项')
21+
# self.frm_advance.pack(expand='yes', side='right', fill='both', padx=15, pady=10)
22+
# self.frm_2 = LabelFrame(self.frm_advance, text='高级配置', width=300)
23+
# self.frm_2.pack(expand='yes', side='top', fill='both', padx=15, pady=10)
24+
25+
self.frm_project = LabelFrame(self.frm_main, text='项目信息')
26+
self.frm_config = LabelFrame(self.frm_main, text='配置信息')
27+
self.frm_operate = LabelFrame(self.frm_main, text='操作')
28+
self.frm_status = LabelFrame(self.frm_main, text='状态')
1929

20-
self.frm_project.pack(expand='yes', side='top',
21-
fill='both', padx=15, pady=10)
30+
self.frm_project.pack(expand='yes', side='top', fill='both', padx=15, pady=10)
2231
self.frm_config.pack(fill='x', padx=15, pady=10)
2332
self.frm_operate.pack(fill='x', padx=15, pady=10)
2433
self.frm_status.pack(side='bottom', fill='x', padx=15, pady=10)
@@ -68,8 +77,11 @@ def init_config(self):
6877
self.cfg_onedir = IntVar(value=0)
6978
self.cfg_noconsole = IntVar(value=1)
7079
self.cfg_clean = IntVar(value=1)
80+
self.cfg_upx = IntVar(value=1) # UPX 默认开启
7181
self.cfg_rename = IntVar()
7282
self.cfg_exe_name = StringVar()
83+
# 自定义配置文件
84+
self.cfg_specfile = StringVar(value='build.spec')
7385
# 子配置框架
7486
self.frm_config_base = LabelFrame(
7587
self.frm_config, text='基本', borderwidth=0)
@@ -80,11 +92,16 @@ def init_config(self):
8092
self.frm_config_other = LabelFrame(
8193
self.frm_config, text='其它', borderwidth=0)
8294
self.frm_config_other.pack(fill='x', padx=10, pady=5, ipady=5)
95+
self.frm_config_spec = LabelFrame(self.frm_config, text='配置文件', borderwidth=0)
96+
self.frm_config_spec.pack(fill='x', padx=10, pady=5, ipady=5)
97+
8398
# 定义按钮
8499
self.btn_noconsole = Checkbutton(
85100
self.frm_config_base, text='关闭控制台', variable=self.cfg_noconsole)
86101
self.btn_clean = Checkbutton(
87102
self.frm_config_base, text='构建前清理', variable=self.cfg_clean)
103+
self.btn_upx = Checkbutton(
104+
self.frm_config_base, text='UPX压缩', variable=self.cfg_upx)
88105
self.btn_isonefile = Checkbutton(
89106
self.frm_config_exe, text='独立执行文件', variable=self.cfg_onefile)
90107
self.btn_isonedir = Checkbutton(
@@ -94,13 +111,18 @@ def init_config(self):
94111
self.entry_rename = Entry(
95112
self.frm_config_other, textvariable=self.cfg_exe_name)
96113

114+
# self.btn_rename = Checkbutton(self.frm_config_spec, text='生成配置文件', variable=self.cfg_specfile)
115+
self.entry_specfile = Entry(self.frm_config_spec, textvariable=self.cfg_specfile)
116+
97117
# 放置按钮
98118
self.btn_isonefile.pack(side='left', fill='x')
99119
self.btn_isonedir.pack(side='left', fill='x')
100120
self.btn_noconsole.pack(side='left', fill='x')
101121
self.btn_clean.pack(side='left', fill='x')
122+
self.btn_upx.pack(side='left', fill='x')
102123
self.btn_rename.pack(side='left', fill='x')
103124
self.entry_rename.pack(fill='x')
125+
self.entry_specfile.pack(fill='x')
104126

105127
# 变量自动切换操作
106128
self.cfg_onefile.trace('w', self.cfg_onefile_trace)
@@ -125,10 +147,14 @@ def init_operate(self):
125147
self.frm_operate, text='清理', command=self.fn_clear)
126148
self.btn_reset = Button(
127149
self.frm_operate, text='重置', command=self.fn_reset)
150+
self.btn_advance = Button(
151+
self.frm_operate, text='高级选项', command=self.fn_toggle_advance)
152+
128153
# 放置按钮
129154
self.btn_build.pack(fill='x', side='left')
130155
self.btn_clear.pack(fill='x', side='left')
131156
self.btn_reset.pack(fill='x', side='left')
157+
self.btn_advance.pack(fill='x', side='right')
132158

133159
def init_status(self):
134160
'''状态栏'''
@@ -137,7 +163,31 @@ def init_status(self):
137163

138164
def fn_build(self):
139165
'''生成可执行文件'''
140-
pass
166+
if not self.status_build:
167+
thread_build = Thread(target=self.fn_thread)
168+
thread_build.setDaemon(True)
169+
thread_build.start()
170+
else:
171+
self.label_status['text'] = '正在打包,请稍后再操作!'
172+
173+
def fn_thread(self):
174+
'''线程执行生成动作'''
175+
if len(self.entry_value_list[0].get()) == 0:
176+
self.label_status['text'] = '请选择源文件'
177+
return
178+
self.status_build = True
179+
cmd = self.fn_build_cmd()
180+
print(cmd)
181+
self.label_status['text'] = '正在打包,请稍等。。。'
182+
try:
183+
# PyInstaller.__main__.run(cmd)
184+
system(' '.join(cmd))
185+
# call(split(' '.join(cmd)), shell=True)
186+
self.status_build = False
187+
self.label_status['text'] = '打包成功!'
188+
except Exception as e:
189+
self.label_status['text'] = str(e)
190+
self.status_build = False
141191

142192
def fn_clear(self):
143193
'''清理生成文件'''
@@ -151,9 +201,19 @@ def fn_reset(self):
151201
self.cfg_onefile.set(1)
152202
self.cfg_noconsole.set(1)
153203
self.cfg_clean.set(1)
204+
self.cfg_upx.set(1)
154205
self.cfg_rename.set(0)
155206
self.cfg_exe_name.set('')
156207

208+
def fn_toggle_advance(self):
209+
'''切换高级选项界面'''
210+
if self.frm_advance.winfo_ismapped():
211+
set_window_center(self.root, width=(self.root.winfo_width() - 400))
212+
self.frm_advance.pack_forget()
213+
else:
214+
set_window_center(self.root, width=(self.root.winfo_width() + 400))
215+
self.frm_advance.pack(expand='yes', side='right', fill='both', padx=15, pady=10)
216+
157217
def fn_select_main(self):
158218
'''选择源文件'''
159219
types = (
@@ -204,6 +264,8 @@ def fn_build_cmd(self):
204264
cmds = []
205265
cmds.append('pyinstaller')
206266
cmds.append('--windowed')
267+
cmds.append('-y')
268+
cmds.append('--noconfirm')
207269
# cmds.append('--filenames=build.spec')
208270
# cmds.append('/usr/local/bin/pyinstaller')
209271

@@ -216,6 +278,9 @@ def fn_build_cmd(self):
216278
cmds.append('--clean')
217279
cmds.append('--noconfirm')
218280

281+
if self.cfg_upx.get() == 0:
282+
cmds.append('--noupx')
283+
219284
if self.cfg_noconsole.get() == 1:
220285
cmds.append('--noconsole')
221286

@@ -234,8 +299,8 @@ def fn_build_cmd(self):
234299

235300
if len(self.entry_value_list[0].get()) > 0:
236301
cmds.append(self.entry_value_list[0].get())
302+
# print(' '.join(cmds))
237303
return cmds
238-
# return ' '.join(cmds)
239304

240305
if __name__ == '__main__':
241306
from tkinter import Tk

0 commit comments

Comments
 (0)