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。
答案 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()
完全没有做任何事情。这解释了为什么GFS
和Oscillators
的魔力似乎顺序发生:它们都发生在主线程中,而两个辅助线程根本不执行任何操作。
当然可以混合wx
和threading
,但混合物有一些粗糙的边缘。例如,单元测试目的可能需要在单独的线程中创建和销毁多个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和其他一些参数调用我的下载线程。我可以多次这样做,没有任何问题。
我的一位读者采用了这个例子并在此处扩展了一点:
希望有所帮助。