python编写windows桌面程序(小Demo)

时间:2022-02-23 09:18:18

前段时间,由于公司业务需求,需要导出腾讯云中的对象存储服务bucket下指定文件夹所有apk文件的下载地址和一些文件夹创建的操作,但因文件较多,人工去遍历肯定不可取,因此就想着撸个python桌面程序。功能比较简单,正好以此记录下学习过程。
1. 开发所需软件
python2.7 , wxPython3.0-for-py2.7 , py2exe0.6.9-for-py2.7 , setuptools0.6-for-py2.7
注:由于腾讯云的对象存储服务python的sdk使用的是2.7版本,加上python3没有向前兼容,因此这里选择2.7版本; wxPython主要是针对python在win下而产生的控件库; py2exe主要是将py文件包装为windows下可执行的exe文件; setuptools主要是用来安装一些第三方python库的时候使用的,当然也可以用pip。上述的软件python版本需要一致。
2. python环境配置
在环境变量添加PYTHON_HOME,地址指向Python安装目录,将PYTHON_HOME添加到Path中,并指向Python安装目录的子目录Scripts
3. 实现需求
准备工作: 下载对象存储服务Python端SDK,使用pip安装 pip install qcloud_cos_v4
具体实现:先看看最后的效果图
python编写windows桌面程序(小Demo)

界面GUI:

     def setupMenuBar(self):
self.CreateStatusBar()
menubar = wx.MenuBar()
menufile = wx.Menu()
mnuabout = menufile.Append(wx.ID_ABOUT, u'&关于', 'about this shit')
mnuexit = menufile.Append(wx.ID_EXIT, u'&退出', 'end program')
menubar.Append(menufile, u'&操作')
self.Bind(wx.EVT_MENU, self.onAbout, mnuabout)
self.Bind(wx.EVT_MENU, self.onExit, mnuexit)
self.SetMenuBar(menubar)

def createUI(self):
panel = wx.Panel(self,-1)
config_channel=wx.StaticText(panel,-1,u"1.配置apk渠道信息:",(10,10))
bt3 = wx.Button(panel,-1,u'一键生成渠道包',(30,40))
userLabel=wx.StaticText(panel,-1,u"2.获取云端指定目录下所有apk下载地址:",(10,90))
self.userText=wx.TextCtrl(panel,-1,"",(120,120),size=(160,-1))
#设置默认的插入点,整数索引,开始位置为0
self.userText.SetInsertionPoint(120)
inputdic=wx.StaticText(panel,-1,u"输入目录名:",(30,120))
bt4 = wx.Button(panel,-1,u'立即获取',(320,120))
tv_download_url=wx.StaticText(panel,-1,u"3.生成apk下载地址:",(10,160))
tv_show_url=wx.StaticText(panel,-1,u"进度:",(30,200))
self.et_url=wx.TextCtrl(panel,-1,"",(90,200),size=(450,-1),style=wx.TE_MULTILINE)
self.et_url.SetInsertionPoint(90)
bt3.Bind(wx.EVT_BUTTON,self.createChannelInfo)
bt4.Bind(wx.EVT_BUTTON,self.createDirectory)

主要生成了菜单栏操作按钮和主界面一些布局控件,按钮和文本等

业务逻辑:
获取apk文件下载地址

    def createDirectory(self,evt):
self.et_url.SetValue(u'正在生成地址中,请稍后...')
#订阅线程回调
Publisher.subscribe(self.getDirFileListCallback, "getdirfilelist")
global apk_dir
apk_dir = self.userText.GetValue().replace(' ','')
GetDirFileListThread(apk_dir)

#获取指定目录的具体信息,包括所有文件的下载地址
class GetDirFileListThread(Thread):
#----------------------------------------------------------------------
def __init__(self,arg1):
"""初始化"""
Thread.__init__(self)
self.str1 = arg1
self.start() # 开启线程

def run(self):
# 配置信息从腾讯云后台获取
cos_client = CosClient(appid, secret_id, secret_key)
request = ListFolderRequest(bucket, u'/'+self.str1+'/')
list_folder_ret = cos_client.list_folder(request)
s = json.loads(json.dumps(list_folder_ret))
if s[u'message'] == u'SUCCESS':

wx.CallAfter(Publisher.sendMessage, "getdirfilelist", s)

else :
wx.CallAfter(Publisher.sendMessage, "getdirfilelist", 'error:'+s[u'message'])

#获取目录下文件信息成功与失败的回调,这里仅示范成功回调
def getDirFileListCallback(self, msg):
cloud_files = msg.data[u'data'][u'infos']
download_url = './apk_channel/'+apk_dir+'_url.txt'
if os.path.exists(download_url) :
os.remove(download_url)
url_file = open(download_url,'a')
# 将获取到的文件下载地址写入文本
for i in range(0, len(cloud_files)):
logging.info(cloud_files[i][u'source_url'])
url_file.write(u''+str(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))+'\t'+cloud_files[i][u'source_url']+'\n\n')
self.et_url.SetValue(u'已完成'+str(i+1)+'/'+str(len(cloud_files))+u',存放于:'+os.getcwdu()+os.sep+'apk_channel'+os.sep+apk_dir+'_url.txt')
url_file.close()

这里并不是直接同步获取下载地址,同步获取容易造成ANR,UI界面卡死,因此采用异步回调的方式,这里使用的是python中的Publisher库配合子线程处理网络请求。Publisher就好比安卓中的EventBus,发布与订阅。

创建App实例:

class App(wx.App):  # 定义一个带有 OnInit()方法的 wx.App的子类
def OnInit(self):
self.frame = MainWindow(None, u'Demo') # 定义窗口名称
self.frame.Show()
self.SetTopWindow(self.frame)
return True
#程序入口
if __name__ == '__main__':
app = App()
app.MainLoop()

# 程序主入口
class MainWindow(wx.Frame):
'''定义一个窗口类'''
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(600, 600))

self.setupMenuBar()
self.Centre()
self.SetCursor( wx.StockCursor( wx.CURSOR_HAND ) )
self.icon = wx.Icon('logo.ico',wx.BITMAP_TYPE_ICO) #设置logo
self.SetIcon(self.icon)
self.filepath = ''
self.filerename = ''
self.Bind(wx.EVT_CLOSE, self.closewindow)
self.createUI()

打包py脚本:
安装py2exe, 编写setup.py文件,代码如下:

# coding=utf-8 
import distutils
import py2exe
options = {
"py2exe": {"packages": ['wx.lib.pubsub']}
}
distutils.core.setup(windows=[{"script": "Demo.py", "icon_resources": [(1, "start.ico")] }], options=options , version = "1.0.0",author = 'jeffer',author_email = 'jeffer7150@163.com')

保存, 执行该setup.py脚本,即可在该目录下生成dist文件夹,里面即生成了Demo.exe文件。