【问题标题】:wxPython threading downloadswxPython 线程下载
【发布时间】:2014-01-29 12:16:25
【问题描述】:

我需要在 wxPython 应用程序中下载 url 列表,但我对线程非常陌生,谁能告诉我一个如何下载链接并将输出放入 wx 控件的工作示例。

【问题讨论】:

    标签: multithreading wxpython


    【解决方案1】:

    很高兴看到您为至少尝试完成这一目标所做的一切。不管怎样,有一些很好的资源可以用来学习如何在 wxPython 中做线程。他们在这里:

    我写了一篇关于使用 urllib/urllib2 下载文件的教程,并在这里请求:

    如果你把这三篇文章结合在一起,你就能得出你的答案。不过,我继续写了一个超级简单的下载器:

    import requests
    import os
    import wx
    import wx.lib.scrolledpanel as scrolled
    
    from threading import Thread
    from wx.lib.pubsub import pub
    
    ########################################################################
    class DownloadThread(Thread):
        """Downloading thread"""
    
        #----------------------------------------------------------------------
        def __init__(self, gnum, url, fsize):
            """Constructor"""
            Thread.__init__(self)
            self.fsize = fsize
            self.gnum = gnum
            self.url = url
            self.start()
    
        #----------------------------------------------------------------------
        def run(self):
            """
            Run the worker thread
            """
            local_fname = os.path.basename(self.url)
            count = 1
            while True:
                if os.path.exists(local_fname):
                    tmp, ext = os.path.splitext(local_fname)
                    cnt = "(%s)" % count
                    local_fname = tmp + cnt + ext
                    count += 1
                else:
                    break
            req = requests.get(self.url, stream=True)
            total_size = 0
            print local_fname
            with open(local_fname, "wb") as fh:
                for byte in req.iter_content(chunk_size=1024):
                    if byte:
                        fh.write(byte)
                        fh.flush()
                    total_size += 1024
                    if total_size < self.fsize:
                        wx.CallAfter(pub.sendMessage, 
                                     "update_%s" % self.gnum,
                                     msg=total_size)
            print "DONE!"
            wx.CallAfter(pub.sendMessage,
                         "update_%s" % self.gnum,
                         msg=self.fsize)
    
    
    ########################################################################
    class MyGauge(wx.Gauge):
        """"""
    
        #----------------------------------------------------------------------
        def __init__(self, parent, range, num):
            """Constructor"""
            wx.Gauge.__init__(self, parent, range=range)
    
            pub.subscribe(self.updateProgress, "update_%s" % num)
    
        #----------------------------------------------------------------------
        def updateProgress(self, msg):
            """"""
            self.SetValue(msg)
    
    ########################################################################
    class MyPanel(scrolled.ScrolledPanel):
        """"""
    
        #----------------------------------------------------------------------
        def __init__(self, parent):
            """Constructor"""
            scrolled.ScrolledPanel.__init__(self, parent)
    
            self.data = []
            self.download_number = 1
    
            # create the sizers
            self.main_sizer = wx.BoxSizer(wx.VERTICAL)
            dl_sizer = wx.BoxSizer(wx.HORIZONTAL)
    
            # create the widgets
            lbl = wx.StaticText(self, label="Download URL:")
            self.dl_txt = wx.TextCtrl(self)
            btn = wx.Button(self, label="Download")
            btn.Bind(wx.EVT_BUTTON, self.onDownload)
    
            # layout the widgets
            dl_sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
            dl_sizer.Add(self.dl_txt, 1, wx.EXPAND|wx.ALL, 5)
            dl_sizer.Add(btn, 0, wx.ALL, 5)
            self.main_sizer.Add(dl_sizer, 0, wx.EXPAND)
    
            self.SetSizer(self.main_sizer)
            self.SetAutoLayout(1)
            self.SetupScrolling()
    
        #----------------------------------------------------------------------
        def onDownload(self, event):
            """
            Update display with downloading gauges
            """
            url = self.dl_txt.GetValue()
            try:
                header = requests.head(url)
                fsize = int(header.headers["content-length"]) / 1024
    
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                fname = os.path.basename(url)
                lbl = wx.StaticText(self, label="Downloading %s" % fname)
                gauge = MyGauge(self, fsize, self.download_number)
    
                sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
                sizer.Add(gauge, 0, wx.ALL|wx.EXPAND, 5)
                self.main_sizer.Add(sizer, 0, wx.EXPAND)
    
                self.Layout()
    
                # start thread
                DownloadThread(self.download_number, url, fsize)
    
                self.download_number += 1
            except Exception, e:
                print "Error: ", e
    
    ########################################################################
    class DownloaderFrame(wx.Frame):
        """"""
    
        #----------------------------------------------------------------------
        def __init__(self):
            """Constructor"""
            wx.Frame.__init__(self, None, title="Downloader", size=(800, 400))
            panel = MyPanel(self)
            self.Show()
    
    #----------------------------------------------------------------------
    if __name__ == "__main__":
        app = wx.App(False)
        frame = DownloaderFrame()
        app.MainLoop()
    

    注意:您需要requests 才能使用此脚本。

    【讨论】: