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

前段时间,由于公司业务需求,需要导出腾讯云中的对象存储服务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
具体实现:先看看最后的效果图

界面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 = '[email protected]')

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

你可能感兴趣的:(python)