Wxpython多线程正在顺序运行线程而不是一次全部运行

时间:2014-02-14 20:33:08

标签: wxpython

import wx
import os
import sys
import wx.lib.plot as plot
import datetime
import urllib
import threading

pathstr = '/media/meant2b/My Passport/C Drive/Convert/GFSMaps/'

class Frame(wx.Frame):
    def __init__(self, parent, id, title):
        style = wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER)
        wx.Frame.__init__(self, parent, id, title=title, size = (1024, 768), style=style)
        self.Center()
        self.panel = wx.Panel(self)
        self.panel.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.panel.SetFocus()
        self.panel.SetBackgroundColour('White')
        self.bitmap = None
        self.PhotoMaxSize_1 = (881)        
        self.CreateMenuBar()
        self.model = 0
        self.map = 0
        self.dMinus = 0
        self.Model = ['00', '06', '12', '18']
        self.MDay = ['000','003','006','009','012','015','018','021','024','027','030','033','036','039','042','045','048','051','054','057','060','063','066','069','072','075','078','081','084','087','090','093','096','099','102','105','108','111','114','117','120','123','126','129','132','135','138','141','144','147','150','153','156','159','162','165','168','171','174','177','180','183','186','189','192','204','216','228','240','252','264','276','288','300','312','324','336','348','360','372','384']
        self.MapType = 0


    def gif1(self, event):
        pathstr = '/'
        for self.dMinus in range(4, -1, -1):
            self.MoveCalendar() #sets date
            for Counter1 in range(0, 4):
                for Counter2 in range(0, 81):
                    if os.path.isfile(pathstr + self.strDate + self.Model[Counter1] + self.MDay[Counter2] + '.gif') == True:
                    continue
                    url = 'http://mag.ncep.noaa.gov/GemPakTier/MagGemPakImages/gfs/' + self.strDate + '/' + self.Model[Counter1] + '/gfs_namer_' + self.MDay[Counter2] + '_1000_500_thick.gif'
                    urllib.urlretrieve(url,str(pathstr + self.strDate + self.Model[Counter1] + self.MDay[Counter2] + '.gif'))
                    statinfo = os.stat(str(pathstr + self.strDate + self.Model[Counter1] + self.MDay[Counter2] + '.gif'))
                    if statinfo.st_size<21000L:
                        os.remove(str(pathstr + self.strDate + self.Model[Counter1] + self.MDay[Counter2] + '.gif'))
                        counter2 = 80

         for Counter1 in range (3, -1, -1):
             url = 'http://mag.ncep.noaa.gov/GemPakTier/MagGemPakImages/gfs/' + self.Model[Counter1] + '/gfs_namer_384_850_temp_mslp_precip.gif'
             urllib.urlretrieve(url,pathstr + '850Temp384.gif')
             statinfo = os.stat(pathstr + '850Temp384.gif')
             if statinfo.st_size<21000:
                 os.remove(pathstr + '850Temp384.gif')
                 continue
             else:
                for Counter2 in range(0, 81):
                    url = 'http://mag.ncep.noaa.gov/GemPakTier/MagGemPakImages/gfs/' + self.Model[Counter1] + '/gfs_namer_' + self.MDay[Counter2] + '_850_temp_mslp_precip.gif'
                    urllib.urlretrieve(url,pathstr + '850Temp' + self.MDay[Counter2] + '.gif')
                    statinfo = os.stat(pathstr + '850Temp' + self.MDay[Counter2] + '.gif')
                    if statinfo.st_size<21000:
                        os.remove(pathstr + '850Temp' + self.MDay[Counter2] + '.gif')
        print('SHOW ME')
        self.VGFS(event)

    def gif2(self, event):
        url = 'http://www.cpc.ncep.noaa.gov/products/precip/CWlink/daily_ao_index/ao.sprd2.gif'
        urllib.urlretrieve(url,pathstr + '/AO.gif')

        url = 'http://www.cpc.ncep.noaa.gov/products/precip/CWlink/pna/nao.sprd2.gif'
        urllib.urlretrieve(url,pathstr + '/NAO.gif')

        url = 'http://www.cpc.ncep.noaa.gov/products/precip/CWlink/pna/pna.sprd2.gif'
        urllib.urlretrieve(url,pathstr + '/PNA.gif')

        url = 'http://www.esrl.noaa.gov/psd/enso/mei/ts.gif'
        urllib.urlretrieve(url,pathstr + '/MEI.gif')
     '''
     And numerous more gifs/pngs as well
     '''

    def All(self, event):
        dl0 = threading.Thread(target = self.GFS(event))
        print('MESHOW')
        dl0.start()

        dl1 = threading.Thread(target = self.Oscillators(event))
        print('MEGO')
        dl1.start()

class App(wx.App):

    def OnInit(self):
        self.frame = Frame(parent = None, id =-1)
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True

if __name__=='__main__':
    app = App()
    app.MainLoop()

我正在跳过大量的代码。当我在wxpython中运行上面的操作时,它运行良好,除了它,它不是同时按顺序运行代码。每个帖子都下载了很多gif&amp; png文件...足够我想分开动作以节省一些时间。它正在调用每个'线程',但它正在等待dl0在运行dl1之前完成。我可以通过查看存储文件的目录来判断。如何更改它以获得它以便它同时调用两个线程?'

我将添加此内容以及我不知道在wxpython与tkinter中的线程是否有所不同。在tkinter中,为了让它工作,我从来没有必要添加Thread.init(self)(这不会让我出于某种原因做__),就像我看到在我见过的wxpython编码中完成的那样。

我真的只想尝试两个单独运行正确的程序,然后将它们组合成一个。我也在从tkinter转到wxpython。

2 个答案:

答案 0 :(得分:2)

在第

dl0 = threading.Thread(target = self.GFS(event))

您要将计算结果self.GFS(event)分配给target。虽然理论上这个结果可能是一个可调用的对象,但它不太可能,我想你真正的意味着

dl0 = threading.Thread(target=self.GFS, args=[event])

当然,这同样适用于dl1

关于线程的一些补充说明

假设我有一些带有一些副作用的简单函数和返回值None,如下所示:

>>> import threading
>>> def foo():
        print "I am FOO!"

现在我可以在一个单独的线程中启动此函数,如下所示:

>>> t = threading.Thread(target=foo)
>>> t.start()
I am FOO!

一旦我使用t方法启动帖子start,它就会查看target是否已定义并且可以调用,并且由于这种情况,它会调用它,foo打印其文本。

如果我错误地将foo本身,foo()错误地分配给参数target,会发生什么?我们来看看:

>>> t = threading.Thread(target=foo())
I am FOO!
>>> t.start()

当我执行赋值时,Python必须计算foo()的值,恰好是None(因为foo没有返回值),并且在此计算期间,foo的副作用被触发。

但是当我使用t启动帖子start()时,target的值为None,这是不可调用的,因此根本不会发生任何事情

在你的情况下,我怀疑无论魔法self.GFS(event)做了什么,它都是在分配期间在主线程内完成的,而dl0.start()完全没有做任何事情。这解释了为什么GFSOscillators的魔力似乎顺序发生:它们都发生在主线程中,而两个辅助线程根本不执行任何操作。

关于wx

的一些补充说明

当然可以混合wxthreading,但混合物有一些粗糙的边缘。例如,单元测试目的可能需要在单独的线程中创建和销毁多个wx.App对象,但wxWidgets(因此wxPython)强烈建立在假设只有一个wx.App - 对象的基础上永远,它存在于主线程中。

我更喜欢分离繁重的计算(当然应该得到自己的线程)和所有wx-Gui-stuff。您可能需要考虑以下模式:

首先,GUI端:

# ...

import wx.lib.newevent

ComputationDoneEvent, EVT_COMPUTATION_DONE = wx.lib.newevent.NewEvent()

# ...

class MainFrame(wx.Frame):

    def __init__(self):
        # ...
        self.Bind(EVT_COMPUTATION_DONE, self.OnComputationDone)

    def OnMainButtonPressed(self, evt):
        # The user pressed the big fat button and wants
        # some heavy computation performed
        t = threading.Thread(target=heavy_computation,
                             args=[self, arg1, arg2],
                             daemon=True)
        t.start()
        self.statusbar.SetStatusText("Busy doing stuff...")
        # eventually disable input, change cursor to busy,
        # whatever is appropriate in your case, and how
        # much it makes sense for the user to proceed
        # with other stuff while waiting for the result.

    def OnComputationDone(self, evt):
        # this gets called later when the computation is done
        self.statusbat.SetStatusText("Result: " + str(evt.result))
        # enable input, change cursor, whatever

现在,重计算方面:

def heavy_computation(mother, arg1, arg2):
    # First, all the stuff that has nothing to do with
    # the GUI
    perform_some_side_effects()
    result = some_more_computations(arg1, arg2)

    # Now we have to inform the wx side that we are done
    evt = ComputationDoneEvent(result=result)
    wx.PostEvent(mother, evt)

当然,对于非常复杂和乏味的东西,您需要提供某种进度表,也许您希望在GUI的某处显示heavy_computation内引发的异常。但我希望你明白这个主意。另请参阅http://wxpython.org/Phoenix/docs/html/lib.newevent.html以获取更完整的示例。

答案 1 :(得分:0)

我无法确定为什么在没有看到更多代码的情况下这不起作用。上个月我确实创建了一个wxPython下载应用程序,尽管你可以看一下灵感:

基本上我只是从线程模块中继承线程,让它使用请求下载文件,然后更新wxPython GUI。要开始下载,我使用url和其他一些参数调用我的下载线程。我可以多次这样做,没有任何问题。

我的一位读者采用了这个例子并在此处扩展了一点:

希望有所帮助。